sparqlGraphLibrary/src/main/java/com/ge/research/semtk/ontologyTools/OntologyInfo.java
private ArrayList<OntologyPath> findExactPaths(HashSet<String> fromClassNames, HashSet<String> targetClassNames, PredicateStats predStats, NodeGroup ng, SparqlConnection conn) throws Exception {
		//   
		//   A form of A* path finding algorithm
		//   See getConnList() for the types of connections that are allowed
		//   Returns a list shortest to longest:  [path0, path1, path2...]
		//        pathX.getStartClassName() == fromClassName
		//        pathX.getEndClassName() == member of targetClassNames
		//        pathX.asList() returns list of triple lists [[className0, att, className1], [className1, attName, className2]...]
			
		long t0 = System.currentTimeMillis();
		this.pathWarnings = new ArrayList<String>();
		ArrayList<OntologyPath> waitingList = new ArrayList<OntologyPath>();
		for (String fromClassName : fromClassNames) {
			waitingList.add(new OntologyPath(fromClassName));
		}
		ArrayList<OntologyPath> ret = new ArrayList<OntologyPath>();
		long numFound = 0;
		HashMap<String, Integer> targetHash = new HashMap<String,Integer>(); // hash of all possible ending classes:  targetHash[className] = 1
		
		/* ISSUE 50:  but perhaps these should be handled by a caller, not by this method
		 * Pathfinding should also find paths
 		 *   A) from the new class to a superclass of an existing class
         *   B) from an existing class to a superclass of the new class.
		 */
		
		// return if there is no endpoint
		if (targetClassNames.isEmpty()) { return ret; }
		
		// set up targetHash[targetClass] = 1
		for (String targetName : targetClassNames) {
			targetHash.put(targetName, 1);
		}
		
		// STOP CRITERIA A: search as long as there is a waiting list 
		while (! waitingList.isEmpty()) {
			// pull one off waiting list
			OntologyPath item = waitingList.remove(0);
			String waitClass = item.getEndClassName();
			OntologyPath waitPath = item;
			
			// STOP CRITERIA B:  Also stop searching if:
			//    this final path (with 1 added connection) will be longer than the first (shortest) already found path
			if (!ret.isEmpty() && 
				(waitPath.getLength() + 1  > ret.get(0).getLength() + pathFindingMaxLengthRange)) {
				this.pathWarnings.add(String.format("Found paths up to length %d.", waitPath.getLength()));
				break;
			} 
			
			// STOP CRITERIA C: stop if path is too long
			if (waitPath.getLength() > pathFindingMaxPathLength) {
				this.pathWarnings.add(String.format("Found paths up to length %d.", pathFindingMaxPathLength));
				break;
			}
			
			// STOP CRITERIA D: too much time spent searching
			// Budget half the time for sorting the results
			if (System.currentTimeMillis() - t0 > pathFindingMaxTimeMsec / 2) {
				this.pathWarnings.add("Path-finding timing out. ");
				break;
			}
			
			// STOP CRITERIA E: found too many
			if (numFound > pathFindingMaxPathCount) {
				while (ret.size() > pathFindingMaxPathCount) {
					ret.remove(ret.size() -1);
				}
				if (predStats == null) {
					this.pathWarnings.add(String.format("Found first %d paths.", pathFindingMaxPathCount));
				} else {
					this.pathWarnings.add(String.format("Stopped at %d raw paths.", pathFindingMaxPathCount));
				}
				break;
			}
			
			// get all one hop connections and loop through them
			for (OntologyPath oConn : this.getConnList(waitClass, predStats)) {
				//  each connection is a path with only one node (the 0th)
				//  grab the name of the newly found class
				String newClass = "";
				OntologyPath newPath = null;
				boolean loopFlag = false;
				
				// if the newfound class is pointed to by an attribute of one on the wait list
				if (oConn.getStartClassName().equals(waitClass)) {
					newClass = oConn.getEndClassName();
					
				} else {
					newClass = oConn.getStartClassName();
				}
				
				// check for loops in the path before adding the class
				// PEC 11/2019: there are some good paths that might have "loops" so this will have to be re-thought
				if (waitPath.containsSubPath(oConn)) {
					loopFlag = true;
				} 
								
				// build the new path
				Triple t = oConn.getTriple(0);
				newPath = waitPath.deepCopy();
				newPath.addTriple(t.getSubject(), t.getPredicate(), t.getObject());

				// if path leads anywhere in domain, store it
				if (this.containsClass(newClass)) {

					// if path leads to a target
					if (targetHash.containsKey(newClass)) {
						// if in full instance mode, path connected to ng must have data
						if (ng == null || this.pathToNgHasInstance(ng, newPath, conn)) {
							ret.add(newPath);
							numFound++;
							if (CONSOLE_LOG) { LocalLogger.logToStdOut(">>>found path " + newPath.debugString()); }
						}

					// if path doens't lead to target
					}  else if (loopFlag == false){
						// if in full instance mode, path must have data
						if (ng == null || this.pathHasInstance(newPath, conn)) {
							waitingList.add(newPath);
							if (CONSOLE_LOG) { LocalLogger.logToStdOut("searching " + newPath.debugString()); }
						}
					}
				}

			}
		}
		this.sortPaths(ret);
		
		if (CONSOLE_LOG) {
			LocalLogger.logToStdOut("These are the paths I found:");
			for (int i=0; i < ret.size(); i++) {
				LocalLogger.logToStdOut(ret.get(i).debugString());
			}
			
			long t1 = System.currentTimeMillis();
			LocalLogger.logToStdOut("findAllPaths time is: " + (t1-t0) + " msec");
		}
		
		return ret;	
	}
/**
	 * Find all paths from fromClassName to one of targetClassNames.
	 * Must be an exact match end-to-end, 
	 * (which only matters when there are predicateStats or instance data being checked)
	 * @param fromClassNames
	 * @param targetClassNames
	 * @return
	 * @throws Exception 
	 */
Find all paths from fromClassName to one of targetClassNames.
Must be an exact match end-to-end,
(which only matters when there are predicateStats or instance data being checked)
@param fromClassNames
@param targetClassNames
@return
@throws Exception
Find all paths from fromClassName to one of targetClassNames . Must be an exact match end - to - end ( which only matters when there are predicateStats or instance data being checked ) @param fromClassNames @param targetClassNames @return @throws Exception
private ArrayList<OntologyPath> findExactPaths(HashSet<String> fromClassNames, HashSet<String> targetClassNames, PredicateStats predStats, NodeGroup ng, SparqlConnection conn) throws Exception {
		A form of A* path finding algorithm
		See getConnList() for the types of connections that are allowed
		Returns a list shortest to longest:  [path0, path1, path2...]
		     pathX.getStartClassName() == fromClassName
		     pathX.getEndClassName() == member of targetClassNames
		     pathX.asList() returns list of triple lists [[className0, att, className1], [className1, attName, className2]...]
		long t0 = System.currentTimeMillis();
		this.pathWarnings = new ArrayList<String>();
		ArrayList<OntologyPath> waitingList = new ArrayList<OntologyPath>();
		for (String fromClassName : fromClassNames) {
			waitingList.add(new OntologyPath(fromClassName));
		}
		ArrayList<OntologyPath> ret = new ArrayList<OntologyPath>();
		long numFound = 0;
		HashMap<String, Integer> targetHash = new HashMap<String,Integer>(); 
		/* ISSUE 50:  but perhaps these should be handled by a caller, not by this method
		 * Pathfinding should also find paths
 		 *   A) from the new class to a superclass of an existing class
         *   B) from an existing class to a superclass of the new class.
		 */
		if (targetClassNames.isEmpty()) { return ret; }
		for (String targetName : targetClassNames) {
			targetHash.put(targetName, 1);
		}
		while (! waitingList.isEmpty()) {
			OntologyPath item = waitingList.remove(0);
			String waitClass = item.getEndClassName();
			OntologyPath waitPath = item;
			 this final path (with 1 added connection) will be longer than the first (shortest) already found path
			if (!ret.isEmpty() && 
				(waitPath.getLength() + 1  > ret.get(0).getLength() + pathFindingMaxLengthRange)) {
				this.pathWarnings.add(String.format("Found paths up to length %d.", waitPath.getLength()));
				break;
			} 
			if (waitPath.getLength() > pathFindingMaxPathLength) {
				this.pathWarnings.add(String.format("Found paths up to length %d.", pathFindingMaxPathLength));
				break;
			}
			if (System.currentTimeMillis() - t0 > pathFindingMaxTimeMsec / 2) {
				this.pathWarnings.add("Path-finding timing out. ");
				break;
			}
			if (numFound > pathFindingMaxPathCount) {
				while (ret.size() > pathFindingMaxPathCount) {
					ret.remove(ret.size() -1);
				}
				if (predStats == null) {
					this.pathWarnings.add(String.format("Found first %d paths.", pathFindingMaxPathCount));
				} else {
					this.pathWarnings.add(String.format("Stopped at %d raw paths.", pathFindingMaxPathCount));
				}
				break;
			}
			for (OntologyPath oConn : this.getConnList(waitClass, predStats)) {
				String newClass = "";
				OntologyPath newPath = null;
				boolean loopFlag = false;
				if (oConn.getStartClassName().equals(waitClass)) {
					newClass = oConn.getEndClassName();
				} else {
					newClass = oConn.getStartClassName();
				}
				if (waitPath.containsSubPath(oConn)) {
					loopFlag = true;
				} 
				Triple t = oConn.getTriple(0);
				newPath = waitPath.deepCopy();
				newPath.addTriple(t.getSubject(), t.getPredicate(), t.getObject());
				if (this.containsClass(newClass)) {
					if (targetHash.containsKey(newClass)) {
						if (ng == null || this.pathToNgHasInstance(ng, newPath, conn)) {
							ret.add(newPath);
							numFound++;
							if (CONSOLE_LOG) { LocalLogger.logToStdOut(">>>found path " + newPath.debugString()); }
						}
					}  else if (loopFlag == false){
						if (ng == null || this.pathHasInstance(newPath, conn)) {
							waitingList.add(newPath);
							if (CONSOLE_LOG) { LocalLogger.logToStdOut("searching " + newPath.debugString()); }
						}
					}
				}
			}
		}
		this.sortPaths(ret);
		if (CONSOLE_LOG) {
			LocalLogger.logToStdOut("These are the paths I found:");
			for (int i=0; i < ret.size(); i++) {
				LocalLogger.logToStdOut(ret.get(i).debugString());
			}
			long t1 = System.currentTimeMillis();
			LocalLogger.logToStdOut("findAllPaths time is: " + (t1-t0) + " msec");
		}
		return ret;	
	}
private ArrayList < OntologyPath > findExactPaths ( HashSet < String > fromClassNames , HashSet < String > targetClassNames , PredicateStats predStats , NodeGroup ng , SparqlConnection conn ) throws Exception { long t0 = System . currentTimeMillis ( ) ; this . pathWarnings = new ArrayList < String > ( ) ; ArrayList < OntologyPath > waitingList = new ArrayList < OntologyPath > ( ) ; for ( String fromClassName : fromClassNames ) { waitingList . add ( new OntologyPath ( fromClassName ) ) ; } ArrayList < OntologyPath > ret = new ArrayList < OntologyPath > ( ) ; long numFound = 0 ; HashMap < String , Integer > targetHash = new HashMap < String , Integer > ( ) ; /* ISSUE 50:  but perhaps these should be handled by a caller, not by this method
		 * Pathfinding should also find paths
 		 *   A) from the new class to a superclass of an existing class
         *   B) from an existing class to a superclass of the new class.
		 */ if ( targetClassNames . isEmpty ( ) ) { return ret ; } for ( String targetName : targetClassNames ) { targetHash . put ( targetName , 1 ) ; } while ( ! waitingList . isEmpty ( ) ) { OntologyPath item = waitingList . remove ( 0 ) ; String waitClass = item . getEndClassName ( ) ; OntologyPath waitPath = item ; if ( ! ret . isEmpty ( ) && ( waitPath . getLength ( ) + 1 > ret . get ( 0 ) . getLength ( ) + pathFindingMaxLengthRange ) ) { this . pathWarnings . add ( String . format ( "Found paths up to length %d." , waitPath . getLength ( ) ) ) ; break ; } if ( waitPath . getLength ( ) > pathFindingMaxPathLength ) { this . pathWarnings . add ( String . format ( "Found paths up to length %d." , pathFindingMaxPathLength ) ) ; break ; } if ( System . currentTimeMillis ( ) - t0 > pathFindingMaxTimeMsec / 2 ) { this . pathWarnings . add ( "Path-finding timing out. " ) ; break ; } if ( numFound > pathFindingMaxPathCount ) { while ( ret . size ( ) > pathFindingMaxPathCount ) { ret . remove ( ret . size ( ) - 1 ) ; } if ( predStats == null ) { this . pathWarnings . add ( String . format ( "Found first %d paths." , pathFindingMaxPathCount ) ) ; } else { this . pathWarnings . add ( String . format ( "Stopped at %d raw paths." , pathFindingMaxPathCount ) ) ; } break ; } for ( OntologyPath oConn : this . getConnList ( waitClass , predStats ) ) { String newClass = "" ; OntologyPath newPath = null ; boolean loopFlag = false ; if ( oConn . getStartClassName ( ) . equals ( waitClass ) ) { newClass = oConn . getEndClassName ( ) ; } else { newClass = oConn . getStartClassName ( ) ; } if ( waitPath . containsSubPath ( oConn ) ) { loopFlag = true ; } Triple t = oConn . getTriple ( 0 ) ; newPath = waitPath . deepCopy ( ) ; newPath . addTriple ( t . getSubject ( ) , t . getPredicate ( ) , t . getObject ( ) ) ; if ( this . containsClass ( newClass ) ) { if ( targetHash . containsKey ( newClass ) ) { if ( ng == null || this . pathToNgHasInstance ( ng , newPath , conn ) ) { ret . add ( newPath ) ; numFound ++ ; if ( CONSOLE_LOG ) { LocalLogger . logToStdOut ( ">>>found path " + newPath . debugString ( ) ) ; } } } else if ( loopFlag == false ) { if ( ng == null || this . pathHasInstance ( newPath , conn ) ) { waitingList . add ( newPath ) ; if ( CONSOLE_LOG ) { LocalLogger . logToStdOut ( "searching " + newPath . debugString ( ) ) ; } } } } } } this . sortPaths ( ret ) ; if ( CONSOLE_LOG ) { LocalLogger . logToStdOut ( "These are the paths I found:" ) ; for ( int i = 0 ; i < ret . size ( ) ; i ++ ) { LocalLogger . logToStdOut ( ret . get ( i ) . debugString ( ) ) ; } long t1 = System . currentTimeMillis ( ) ; LocalLogger . logToStdOut ( "findAllPaths time is: " + ( t1 - t0 ) + " msec" ) ; } return ret ; }
Find all paths from fromClassName to one of targetClassNames.
Find all paths from fromClassName to one of targetClassNames .
//    //   A form of A* path finding algorithm //   See getConnList() for the types of connections that are allowed //   Returns a list shortest to longest:  [path0, path1, path2...] //        pathX.getStartClassName() == fromClassName //        pathX.getEndClassName() == member of targetClassNames //        pathX.asList() returns list of triple lists [[className0, att, className1], [className1, attName, className2]...] // hash of all possible ending classes:  targetHash[className] = 1 // return if there is no endpoint // set up targetHash[targetClass] = 1 // STOP CRITERIA A: search as long as there is a waiting list  // pull one off waiting list // STOP CRITERIA B:  Also stop searching if: //    this final path (with 1 added connection) will be longer than the first (shortest) already found path // STOP CRITERIA C: stop if path is too long // STOP CRITERIA D: too much time spent searching // Budget half the time for sorting the results // STOP CRITERIA E: found too many // get all one hop connections and loop through them //  each connection is a path with only one node (the 0th) //  grab the name of the newly found class // if the newfound class is pointed to by an attribute of one on the wait list // check for loops in the path before adding the class // PEC 11/2019: there are some good paths that might have "loops" so this will have to be re-thought // build the new path // if path leads anywhere in domain, store it // if path leads to a target // if in full instance mode, path connected to ng must have data // if path doens't lead to target // if in full instance mode, path must have data