package coverage.graph; import java.lang.reflect.Array; import java.util.ArrayList; import java.util.Iterator; import java.util.List; /** * * * Three graph properties must be satisfied for computing coverage: *
  • one initial node and at least one ending node. *
  • exsit a path from the inital node to any node *
  • exist an path from any node to at least one of the ending nodes. *
    The last two properties also called in the class 'connected' * * @author Wuzhi Xu, Date: Dec 12, 2006 * Modified by Nan Li * */ public class Graph extends GraphBase{ //Node start; List starts;//initial nodes List ends; //final nodes String[] infeasiblePrimePathsString;//store infeasible prime paths String[] infeasibleEdgePairsString;//store infeasible edge-pairs //get infeasible prime paths public String[] getInfeasiblePrimePathsString(){ return infeasiblePrimePathsString; } //set initial nodes public void setInitialNode(List starts) { this.starts = starts; } //get the initial nodes public List getInitialNode() { return starts; } /** * * @param n * @return true if the node n is one of the initial nodes else return false */ public boolean isInitialNode(Node n) { if(starts == null || starts.size() == 0) return false; return starts.contains(n); } /** * * @param n * @return true if the node n is one of the final nodes else return false */ public boolean isEndingNode(Node n) { if(ends == null || ends.size() == 0) return false; return ends.contains(n); } /** * * @return an iterator of final nodes */ public Iterator getEndingNodeIterator() { if(ends == null) ends = new ArrayList(); return ends.iterator(); } /** * * @return an iterator of initial nodes */ public Iterator getInitialNodeIterator() { if(starts == null) starts = new ArrayList(); return starts.iterator(); } /** * * @return the size of edges */ public int sizeOfEdges() { return edges.size(); } /** * * @return the size of all nodes in a graph */ public int sizeOfNodes() { return nodes.size(); } /** * * @return the number of final nodes if final nodes are not null else return 0 */ public int sizeOfEndingNode() { if(ends != null) return ends.size(); else return 0; } /** * * @return the number of initial nodes if initial nodes are not null else return 0 */ public int sizeOfInitialNode() { if(starts != null) return starts.size(); else return 0; } /** * add a node n to the final nodes set * @param n */ public void addEndingNode(Node n) { if(ends == null) ends = new ArrayList(); ends.add(n); } /** * add a node n to the initial nodes set * @param n */ public void addInitialNode(Node n) { if(starts == null) starts = new ArrayList(); starts.add(n); } /** * After generating the spanning tree for graph. This method extends the paths in the * spanning tree to the paths having ending nodes. * @return * @throws InvalidGraphException if the graph is invalid, or there is a dead loop */ public List findTestPath() throws InvalidGraphException { List paths = findSpanningTree(); List result = new ArrayList(); //part 1: find all //find all possible test path existing in the spanning tree for(int i = 0;i < paths.size();i++) { Path p = paths.get(i); //if the last node of the path is one of the final nodes, add it to result, ignore the rest, and jump to the next path if(ends.contains(p.getEnd())) { result.add(p); paths.remove(i); i--; continue; } //for other paths, which are, paths contains at least one node that is one of the final nodes //if the path contains one of the final nodes, get the subpath from the initial node to this node //and check if this subpath has been included in the result, if not, add it to the result for(int j = 0;j < ends.size();j++) { //check if the path p has one of the final nodes int index = p.indexOf(ends.get(j)); if(index != -1) { //get a subpath from one initial node to this final node Path subpath = p.subPath(0, index+1); boolean exist = false;//a sign whether a path is a subpath of any path of result //if the subpath is a sub path of the result, do nothing and exit from the loop for(int k = 0;k < result.size();k++) if(subpath.isSubpath(result.get(k))) { exist = true; break; } //if the path is not a subpath of any path of the result, add it to result if(!exist) result.add(subpath); }//end if }//end for loop with variable j }//end for loop with variable i //throw an exception if there is not any test path in a spanning tree, which means there is no ending node //or ending node is not connected if(result.size()==0) throw new InvalidGraphException("No ending node."); //part 2: extend all paths in spanning tree to test paths, that is, all paths will have final nodes. int oldsize = 0; do { oldsize = paths.size(); for(int j = 0;j < result.size();j++) for(int i = 0;i < paths.size();i++) { Path testPath = result.get(j); Path path = paths.get(i); //if the last node of path is included in the test path, put the rest subpath from this node right after path int index = testPath.indexOf(path.getEnd()); if(index != -1) { Path subpath = testPath.subPath(index+1); path.extendPath(subpath); result.add(path); paths.remove(i); i--; } } }while(oldsize-paths.size() > 0);//after one loop, the size of paths should be reduced; the while loop will be stopped if no path is removed from paths //throw an exception if there exists some paths that never reach an ending node. if(paths.size() != 0) { String pathStr = ""; for(Path p:paths) pathStr += " " + p.toString(); throw new InvalidGraphException("some paths, " + pathStr + ", never reach an ending node."); } return result; } /** * Create the spanning tree for a graph. The tree is represented by a list of paths that start from the * initial nodes * * @return a list of paths starting from each initial node and all nodes have been reached in a graph * @throws InvalidGraphException */ public List findSpanningTree() throws InvalidGraphException { //validate whether the graph is valid validate(); //a list of paths to return the expected paths List result = new ArrayList(); //go through all paths from each initial node for(int j = 0; j < starts.size();j++) { //add all nodes to nodesCopy List nodesCopy = new ArrayList(); for(int i = 0;i < nodes.size();i++) nodesCopy.add(nodes.get(i)); //remove all initial nodes from nodesCopy for(int i = starts.size() - 1;i >= 0;i--) { int index = nodes.indexOf(starts.get(i)); nodesCopy.remove(index); } //initialize each path with one initial node List paths = new ArrayList(); paths.add(new Path(starts.get(j))); //create paths //get paths from one initial node //paths starts from an initial node, keep expanding itself, and check if all nodes except initial nodes have been reached //put paths into result if the corresponding node has been reached //stop while looping when all paths have been removed from paths, which means all nodes have been reached in a graph while(paths.size() != 0) { //from each initial node, go through each possible path for(int i = 0;i < paths.size();i++) { Path path = paths.get(i); Node end = path.getEnd(); Iterator outEdges = end.getOutGoingIterator(); int count = 0; while(outEdges.hasNext()) { count++; //if the edge is the last edge to go through if(count == end.sizeOfOutEdges()) path.extendPath(outEdges.next().getDest());//extend path itself else { Path newPath = (Path)path.clone();//copy path and extend the copy newPath.extendPath(outEdges.next().getDest()); paths.add(i+1, newPath); i++;//add one to variable i to avoid keeping running in the for loop }//end if-else }//end while loop }//end for loop //put paths in List result when the expected node has been reached for(int i = 0;i < paths.size();i++) { Path path = paths.get(i); Node end = path.getEnd(); //if a node is just being reached, remove it from nodesCopy if(nodesCopy.contains(end)) { nodesCopy.remove(end); } //if a node has been reached, put the path to which the node belongs to result else { paths.remove(i); i--;//subtract one from i to keep looping the paths because one path has been removed from paths result.add(path); } } }//end while loop }//end for loop with variable j return result; } /** * find prime path coverage that do not cover infeasible prime paths. But it is not ensured that the set of test path is minimal * * @return * @throws InvalidGraphException */ public List findPrimePathCoverage(String infeasiblePrimePathsString) throws InvalidGraphException { List primes = findPrimePaths1(infeasiblePrimePathsString); long start = System.nanoTime(); List testPaths = findTestPath(); //List primes = findPrimePathsWithSidetrips(infeasiblePrimePathsString); for(int i = 0;i primePathsList = findPrimePaths(); List primePathsWithSidetripsList = findPrimePaths1(infeasiblePrimePathsString); //initialization List selectedPrimePaths = new ArrayList(); List selectedPrimePathsWithSidetrips = new ArrayList(); //put all prime paths that are toured by this path directly into selectedPrimePaths for(int z = 0;z < primePathsList.size();z++) { if(primePathsList.get(z).isSubpath(primes.get(i))) selectedPrimePaths.add(primePathsList.get(z)); } //put all prime paths that are toured by this path with sidetrips into selectedPrimePathsWithSidetrips for(int z = 0;z < primePathsWithSidetripsList.size();z++) { if(primePathsWithSidetripsList.get(z).isSubpath(primes.get(i))) selectedPrimePathsWithSidetrips.add(primePathsWithSidetripsList.get(z)); } //System.out.println("test path: " + "i " + primes.get(i)); for(int z = 0; z < selectedPrimePaths.size();z++) { // System.out.println("selectedPrimePaths: " + selectedPrimePaths.get(z)); } for(int z = 0; z < selectedPrimePaths.size();z++) { // System.out.println("selectedPrimePathsWithSidetrips: " + selectedPrimePathsWithSidetrips.get(z)); } //for the other test paths for(int j = 0;j < primes.size();j++) { boolean sign = false;//a sign for determine whether selected prime paths are also toured by the other test paths //if exists one prime path is not toured by the other test path, set true to the sign for(int x = 0;x < selectedPrimePaths.size();x++) { if(!selectedPrimePaths.get(x).isSubpath(primes.get(j))) sign = true; } for(int x = 0;x < selectedPrimePathsWithSidetrips.size();x++) { if(!selectedPrimePathsWithSidetrips.get(x).isSubpath(primes.get(j))) sign = true; } // System.out.println("test path: " + "j " + primes.get(j)); // System.out.println("sign: " + sign); //remove the test path if it is redundant if(sign == false && !primes.get(i).equals(primes.get(j))) { primes.remove(i); i--; break; } } } long end = System.nanoTime(); long duration = end - start; //System.out.println("running time of prime path coverage = " + duration); /* for(int i = 0;i < primes.size();i++) { Path prime = primes.get(i); System.out.println("second prime list: " + "i " + prime); }*/ return primes; } public List findPrimePathCoverageWithInfeasibleSubPath(String infeasiblePrimePathsString, List infeasibleSubpaths) throws InvalidGraphException{ List result = new ArrayList(); List testPathsForPrimePaths = findPrimePathCoverage(infeasiblePrimePathsString); List tempTestPathsForPrimePaths = new ArrayList(); List tempPrimes = new ArrayList(); /*List subPaths = new ArrayList(); Path path1 = new Path(new Node("2")); path1.extendPath(new Node("3")); path1.extendPath(new Node("1")); path1.extendPath(new Node("2")); path1.extendPath(new Node("3")); subPaths.add(path1);*/ List subPaths = new ArrayList(); if(infeasibleSubpaths != null){ for(int a = 0;a < infeasibleSubpaths.size();a++){ subPaths.add(infeasibleSubpaths.get(a)); } } /* Path path1 = new Path(new Node("3")); path1.extendPath(new Node("4")); path1.extendPath(new Node("6")); path1.extendPath(new Node("2")); path1.extendPath(new Node("3")); path1.extendPath(new Node("4")); path1.extendPath(new Node("6")); path1.extendPath(new Node("2")); // path1.extendPath(new Node("1")); Path path2 = new Path(new Node("3")); path2.extendPath(new Node("5")); path2.extendPath(new Node("6")); path2.extendPath(new Node("2")); path2.extendPath(new Node("3")); path2.extendPath(new Node("4")); path2.extendPath(new Node("6")); // path2.extendPath(new Node("7")); // path2.extendPath(new Node("1")); subPaths.add(path1); subPaths.add(path2);*/ /* Path path2 = new Path(new Node("2")); path2.extendPath(new Node("3")); path2.extendPath(new Node("1")); path2.extendPath(new Node("2")); path2.extendPath(new Node("3")); System.out.println("path1: " + path1); System.out.println("path2: " + path2); System.out.println("path1 is equal to path2: " + path1.equals(path2));*/ for(int i = 0; i < testPathsForPrimePaths.size();i++){ Path testPath = testPathsForPrimePaths.get(i); //System.out.println("test path: " + testPath); for(int j = 0; j < subPaths.size();j++){ Path infeasibleSubPath = subPaths.get(j); // System.out.println("infeasibleSubPath: " + infeasibleSubPath); if(infeasibleSubPath.isSubpath(testPath)){ testPathsForPrimePaths.remove(i); i--; //break; //check the prime paths that are covered by the deleted test path can be covered by other test paths //if not, try to generate another test path to cover it; else, give up //tempPrimes stores prime paths that are toured by testPath //for(int i = 0; i < testPathsForPrimePaths.size();i++){ // Path testPath = testPathsForPrimePaths.get(i); List primes = findPrimePaths1(infeasiblePrimePathsString); for(int k = 0; k < primes.size();k++){ boolean exist = false; //a sign for distinguishing existed prime paths boolean exist1 = false; //a sign for whether a prime path is a subpath of an infeasible sub path //set exist to true if there exists the same path in tempPrimes as the one in primes //get rid of redundant prime paths stored in tempPrimes for(int k1 = 0; k1 < tempPrimes.size();k1++){ if(tempPrimes.get(k1).equals(primes.get(k))) exist = true; } for(int k2 = 0; k2 < subPaths.size(); k2++){ if(primes.get(k).isSubpath(subPaths.get(k2))){ exist1 = true; break; } } if(primes.get(k).isSubpath(testPath) && !exist && !exist1) tempPrimes.add(primes.get(k)); }//end for loop of variable k //check if paths in tempPrimes can be toured by other test paths //if yes, remove it from tempPrimes // System.out.println("test path: " + testPath); for(int l = 0; l < tempPrimes.size();l++){ Path tempPrimes1 = tempPrimes.get(l); // System.out.println("temp prime: " + tempPrimes1); for(int m = 0; m < testPathsForPrimePaths.size();m++){ // System.out.println("test paths1: " + testPathsForPrimePaths.get(m)); if(tempPrimes1.isSubpath(testPathsForPrimePaths.get(m)) && !testPathsForPrimePaths.get(m).equals(testPath)){ tempPrimes.remove(l); l--; break; } } }//end for loop of variable l //try to generate another test path that can tour paths in tempPrimes // one way to generate test path for(int n = 0; n < tempPrimes.size(); n++){ Path tempPrime = tempPrimes.get(n); // for(int x = 0; x < testPathsForPrimePaths.size(); x++){ for(int x = 0; x < findTestPath().size(); x++){ Path pathForHead = findTestPath().get(x); Path subPathForHead = null; int index1 = pathForHead.lastIndexOf(tempPrime.get(0)); if(index1 != -1 && starts.indexOf(pathForHead.get(0)) != -1){ //System.out.println("n:" + n); subPathForHead = pathForHead.subPath(0, index1); //System.out.println("subPathForHead:" + subPathForHead.toString()); if(index1 == 0) subPathForHead.extendPath(tempPrime.subPath(1, tempPrime.size())); else subPathForHead.extendPath(tempPrime); //tempPrime = subPathForHead; } for(int y = 0; y < testPathsForPrimePaths.size(); y++){ //System.out.println("y:" + y); Path pathForTail = testPathsForPrimePaths.get(y); Path subPathForTail = null, finalPath = null, finalPath1 = null; //System.out.println("PathForTail: " + pathForTail.toString()); if(subPathForHead != null){ //System.out.println("subPathForHead: " + subPathForHead.toString()); finalPath = subPathForHead; if(ends.indexOf(finalPath.getEnd()) == -1){ int index2 = pathForTail.indexOf(finalPath.getEnd()); if(index2 != -1){ subPathForTail = pathForTail.subPath(index2 + 1, pathForTail.size()); finalPath.extendPath(subPathForTail); // finalPath1 = finalPath; // finalPath = subPathForTail; } } // if(finalPath1 != null) // System.out.println("finalPath1: " + finalPath1.toString()); boolean is = true, existed = false; //if an infeasible subpath is a sub-path of the finalPath, set is to false for(int z = 0; z < subPaths.size();z++) if(subPaths.get(z).isSubpath(finalPath)) is = false; //if the finalPath is the same as any one in the test paths, set existed to true for(int z1 = 0;z1 < testPathsForPrimePaths.size();z1++){ if(testPathsForPrimePaths.get(z1).equals(finalPath)){ existed = true; // System.out.println("existed: " + existed); break; } } // System.out.println("finalPath: " + finalPath.toString()); // System.out.println("is: " + is); //if a final path does not include any infeasible sub-path and is not equal to any existing test path //and the last node is one of the final nodes, add it to test paths list boolean existed1 = false; if(is == true && existed == false && ends.indexOf(finalPath.getEnd()) != -1){ //if the testPrime has been included in other existing test path, set extisted1 to true for(int z2 = 0;z2 < testPathsForPrimePaths.size();z2++){ if(tempPrime.isSubpath(finalPath) && tempPrime.isSubpath(testPathsForPrimePaths.get(z2))){ existed1 = true; } } //if existed1 is equal to false, i.e. the testPrime has not been toured by any other test path, add the finalPath to test paths list if(existed1 == false){ testPathsForPrimePaths.add(finalPath); // tempTestPathsForPrimePaths.add(finalPath); } //System.out.println("finalPath: " + finalPath.toString()); } // } }//end if }//end for loop of varaile y }// end for loop of variable x //check if the new generated path contains infeasible sub path }//end for loop of variable n //another way to generate test path }//end if }//end for loop of variable j }//end for loop of variable i //return tempTestPathsForPrimePaths; return testPathsForPrimePaths; //return tempPrimes; } /* * Effects: get a minimal set of test paths for Edge-Pair Coverage that do not cover infeasible edge-pairs * */ public List findEdgePairCoverage(String infeasibleEdgePairs) throws InvalidGraphException{ //get test paths List testPaths = findTestPath(); //get edge pairs List edgePairs = findEdgePairs(infeasibleEdgePairs); //get a copy of edge-pairs // List edgePairsCopy = new ArrayList(); //// for(int i = 0;i < edgePairs.size();i++) // edgePairsCopy.add(edgePairs.get(i)); //new array list to keep test paths for Edge-Pair Coverage List result = new ArrayList(); jumpofloop: for(int i = 0; i < edgePairs.size();i++){ // get a prime path Path edgePair = edgePairs.get(i); for(int k = 0;k < result.size();k++){ if(edgePair.isSubpath(result.get(k))) continue jumpofloop; } boolean extendHead = false; boolean extendTail = false; //get the first node and last node of a prime path Node head = edgePair.get(0); Node tail = edgePair.getEnd(); //if the first node is the initial node of the graph //set true to extendHead if(starts.indexOf(head) != -1) extendHead = true; //if the last node is one of the final nodes of the graph //set true to extendTail if(ends.contains(tail)) extendTail = true; for(int j=0;j edgePairsList = findEdgePairs(); List edgePairsWithSidetripsList = findEdgePairs(infeasibleEdgePairs); //initialization List selectedEdgePairs = new ArrayList(); List selectedEdgePairsWithSidetrips = new ArrayList(); //put all edge pairs that are toured by this path directly into selectedEdgePairs for(int z = 0;z < edgePairsList.size();z++) { if(edgePairsList.get(z).isSubpath(result.get(i))) selectedEdgePairs.add(edgePairsList.get(z)); } //put all edge-pairs that are toured by this path with sidetrips into selectedPrimePathsWithSidetrips for(int z = 0;z < edgePairsWithSidetripsList.size();z++) { if(edgePairsWithSidetripsList.get(z).isSubpath(result.get(i))) selectedEdgePairsWithSidetrips.add(edgePairsWithSidetripsList.get(z)); } //for the other test paths for(int j = 0;j < result.size();j++) { boolean sign = false;//a sign for determine whether selected edge paris are also toured by the other //if exists one edge pair is not toured by the other test path, set true to the sign for(int x = 0;x < selectedEdgePairs.size();x++) { if(!selectedEdgePairs.get(x).isSubpath(result.get(j))) sign = true; } for(int x = 0;x < selectedEdgePairsWithSidetrips.size();x++) { if(!selectedEdgePairsWithSidetrips.get(x).isSubpath(result.get(j))) sign = true; } //remove the test path if it is redundant if(sign == false && !result.get(i).equals(result.get(j))) result.remove(i); } } /* this part is not complete //attempt to minimize the set of test path, step2 //get rid of test paths that are subpaths of any other test path List edgePairsCopy = findEdgePairs(); List finalResult = new ArrayList(); //edgePairsSet storing test paths for edge pairs List edgePairsSet = new ArrayList(); for(int i = 0; i < edgePairsCopy.size();i++) edgePairsSet.add(edgePairsCopy.get(i)); //resultSet storing test paths for edge-pair coverage List resultSet = new ArrayList(); for(int i = 0; i < result.size();i++) resultSet.add(result.get(i)); for(int i = 0;i < edgePairsSet.size();i++) { int counter = 0; Path edgePair = edgePairsSet.get(i); List temp = new ArrayList(); for(int j = 0;j < resultSet.size();j++) { if(edgePair.isSubpath(resultSet.get(j))) { counter++; temp.add(resultSet.get(j)); } } if(counter == 1){ finalResult.add(temp.get(0)); edgePairsSet.remove(i); } } */ return result; } /** * @return: a minimal set of test paths for Edge coverage using sidetrips * */ public List findEdgeCoverage() throws InvalidGraphException { List result = findTestPath(); List resultCopy = new ArrayList(); for(int i = 0;i < result.size();i++) resultCopy.add(result.get(i)); //use sidetrip to minimize the set of test path for(int i = result.size() - 1;i > -1;i--) for(int j = 0;j < resultCopy.size();j++) { Path p1 = result.get(i); Path p2 = resultCopy.get(j); if(p1 != p2 && p1.sidetrip(p2)) resultCopy.remove(j); } //to minimize the test paths set //remove redundant paths if all edges have been reached by any other path List resultCopy3 = new ArrayList(); //make a copy of resultCopy List resultCopy2 = new ArrayList(); for(int i = 0;i < resultCopy.size();i++) resultCopy2.add(resultCopy.get(i)); //make a copy of nodeCopy List edgeCopy = new ArrayList(); for(int i = 0;i < edges.size();i++) edgeCopy.add(edges.get(i)); //add paths one by one from resultCopy2 to resultCopy3 until all nodes have been reached for(int i = 0;i < resultCopy2.size();i++) { Path path = resultCopy2.get(i); resultCopy3.add(path); //compare each node in all paths to all nodes in the graph, remove a node from nodeCopy if the node has been reached by one path for(int j = 0;j < path.getEdgeList().size();j++) { for(int z = 0;z < edgeCopy.size();z++) { //if an edge in edgeCopy is being reached by one path, remove it from edgeCopy boolean sign; if(edgeCopy.get(z).equals(path.getEdgeList().get(j))) { sign = edgeCopy.remove(edgeCopy.get(z)); } } } //when all edges have been reached, jump out of the for loops if(edgeCopy.size() == 0) break; } return resultCopy3; } /** * Goal:Find a minimal set of test paths for node coverage using detours * Actually it is really hard to achieve it. * For instance: we have paths from findTestPath() * p1: [0,1,2,3,1,5,6] * p2: [0,1,5,6] * p3: [0,4,4,6] * p4: [0,4,6] * The minimal set of test paths for node coverage should be p1 and p4 * However, using touring with detours, we get p1 and p3 */ public List findNodeCoverage() throws InvalidGraphException { //get all possible test paths List result = findTestPath(); //make a copy to resultCopy List resultCopy = new ArrayList(); for(int i = 0;i < result.size();i++) resultCopy.add(result.get(i)); //for each path in result check if exists any path in resultCopy tours it with Detours //if p2 tours p1 with Detours, remove the p2 from the resultCopy for(int i = 0;i < result.size();i++) for(int j=0;j < resultCopy.size();j++) { Path p1 = result.get(i); Path p2 = resultCopy.get(j); if(p1 != p2 && p1.detour(p2)){ resultCopy.remove(j); } } //remove redundent nodes from paths //e.g. all nodes should appear once in paths of node coverage //thus,the result is [0,4,6] rather than [0,4,4,6] for(int i = 0;i < resultCopy.size();i++){ Path p = resultCopy.get(i); for(int j = 0;j < p.size()-1;j++){ if (p.get(j).equals(p.get(j+1))) p.remove(j); } } //the last step to minimize the set //clear up the test paths that can tour any other path with Detours again //make another copy of current prime paths List resultCopy1 = new ArrayList(); for(int i = 0; i < resultCopy.size();i++) resultCopy1.add(resultCopy.get(i)); //for each path in result check if exists any path in resultCopy tours it with Detours //if p2 tours p1 with Detours, remove the p2 from the resultCopy for(int i = 0;i < resultCopy.size();i++) for(int j=0;j < resultCopy1.size();j++) { Path p1 = resultCopy.get(i); Path p2 = resultCopy1.get(j); if(p1 != p2 && p1.detour(p2)){ resultCopy1.remove(j); } } List resultCopy3 = new ArrayList(); //make a copy of resultCopy List resultCopy2 = new ArrayList(); for(int i = 0;i < resultCopy1.size();i++) resultCopy2.add(resultCopy1.get(i)); //make a copy of nodeCopy List nodeCopy = new ArrayList(); for(int i = 0;i < nodes.size();i++) nodeCopy.add(nodes.get(i)); //add paths one by one from resultCopy2 to resultCopy3 until all nodes have been reached for(int i = 0;i < resultCopy2.size();i++) { Path path = resultCopy2.get(i); resultCopy3.add(path); //compare each node in all paths to all nodes in the graph, remove a node from nodeCopy if the node has been reached by one path for(int j = 0;j < path.size();j++) { for(int z = 0;z < nodeCopy.size();z++) { int index = nodeCopy.indexOf(path.get(j)); if(index >= 0) nodeCopy.remove(index); } } //check if all nodes have been reached if(nodeCopy.size() == 0) break; } return resultCopy3; } /** * A valid graph must have the following three properties : *
  • at least one initial node and at least one final node *
  • exist a path for any node that can be reached by the initial node(connected) *
  • exist a path for any node that can reach at least one ending node(dead loop) * This method check the first and second properties. * */ public void validate() throws InvalidGraphException { //throw InvalidGraphException if no initial nodes /* int index = nodes.indexOf(start); if(start == null || index == -1) throw new InvalidGraphException("No initial node."); */ if(starts == null || starts.size()== 0) throw new InvalidGraphException("No initial nodes."); //throw InvalidGraphException if no final nodes if(ends == null || ends.size()== 0) throw new InvalidGraphException("No ending nodes."); //check if one node has not outgoing edge but not an ending node. // for(int i=0;i linkedNodes = new ArrayList(); List nodesCopy = new ArrayList(); //put all nodes into nodesCopy List for(int i = 0;i < nodes.size();i++) nodesCopy.add(nodes.get(i)); //add the initial node into the linkedNodes //and remove the initial node from the nodesCopy for(int i = 0; i < starts.size();i++) linkedNodes.add(starts.get(i)); for(int i = starts.size() - 1;i >= 0;i--) { int index = nodes.indexOf(starts.get(i)); if(index >= 0 && index < nodesCopy.size()){ nodesCopy.remove(index); } } //for each node that is connected in the graph, //if the node is included in the linkedNodes, remove it from the nodesCopy and add it to the linkedNodes for(int i = 0;i < linkedNodes.size();i++) { Iterator outEdge = linkedNodes.get(i).getOutGoingIterator(); while(outEdge.hasNext()) { Node des = outEdge.next().getDest(); if(nodesCopy.contains(des)) { nodesCopy.remove(des); linkedNodes.add(des); } } } //if there is any node left in the nodesCopy, print them with a InvalidGraphException if(nodesCopy.size() != 0 && nodesCopy.size() != 1) { String nodeStr = ""; for(Node node:nodesCopy) nodeStr += " " + node.toString(); throw new InvalidGraphException("The Nodes: " + nodeStr + " are not connected."); } else if(nodesCopy.size() == 1) { String nodeStr = ""; for(Node node:nodesCopy) nodeStr += " " + node.toString(); throw new InvalidGraphException("The Node: " + nodeStr + " is not connected."); } } /** * return simple paths */ public List findSimplePaths() { Edge e; Path p, pnew; int lastStart = 0; int curSize; List simplePaths = new ArrayList(); // Initialize the paths list with the edges for (int i=0; i findNodes(){ List nodesPath = new ArrayList(); for (int i=0; i findEdges(){ List edgesPath = new ArrayList(); for (int i = 0; i < edges.size(); i++) { Path p = new Path(edges.get(i)); edgesPath.add(p); } return edgesPath; } /** * Effects: return edge-pair requirements of a graph */ public List findEdgePairs(){ long start = System.nanoTime(); List edgesPath = new ArrayList(); //for each edge, if its destination node has an outgoing edge //add this outgoing edge to it for (int i = 0; i < edges.size(); i++) { if(edges.get(i).dest.sizeOfOutEdges() != 0) { Iterator ie = edges.get(i).dest.getOutGoingIterator(); while(ie.hasNext()){ Path p = new Path(edges.get(i)); Path p1 = new Path(ie.next().dest); p.extendPath(p1); edgesPath.add(p); } } //cover edges that are not covered by paths of length of 2 else if(edges.get(i).dest.sizeOfOutEdges() == 0 && starts.indexOf(edges.get(i).src) != -1) { Path p = new Path(edges.get(i)); edgesPath.add(p); } } /* long end = System.nanoTime(); long duration = end - start; System.out.println("time taken: " + duration);*/ return edgesPath; } /** * Effects: return a path list of prime paths */ public List findPrimePaths() { //long start = System.nanoTime(); //get all simple paths List simplePaths = findSimplePaths(); //generate prime paths only if there is one simple path at least if(simplePaths.size() > 0){ //sort list in term of the size of path quickSort(simplePaths, 1, simplePaths.size()); List primePaths = new ArrayList(); primePaths.add(simplePaths.get(simplePaths.size()-1)); for(int i = simplePaths.size() - 2;i > -1;i--) { boolean isSubpath = false; for(int j = 0;j < primePaths.size();j++) if(simplePaths.get(i).isSubpath(primePaths.get(j))) { isSubpath=true; break; } if(!isSubpath) primePaths.add(simplePaths.get(i)); } return primePaths; } // long end = System.nanoTime(); // long duration = end - start; // System.out.println("The running time: " + duration); //if there is no simple path, return an empty List return simplePaths; } /** * a list of paths including all feasible prime paths and paths touring infeasible paths with sidetrips * the sidetrips are some of feasible prime paths * @param infeasiblePrimePaths * @return */ public List findPrimePaths1(String infeasiblePrimePaths) { List simplePaths=findSimplePaths(); //sort list in term of the size of path quickSort(simplePaths, 1, simplePaths.size()); List primePaths = new ArrayList(); primePaths.add(simplePaths.get(simplePaths.size()-1)); for(int i = simplePaths.size()-2;i >- 1;i--) { boolean isSubpath = false; for(int j = 0;j < primePaths.size();j++) if(simplePaths.get(i).isSubpath(primePaths.get(j))) { isSubpath = true; break; } if(!isSubpath) primePaths.add(simplePaths.get(i)); } //get a copy of prime paths List primePathsCopy = new ArrayList(); for(int i = 0; i < primePaths.size();i++) primePathsCopy.add(primePaths.get(i)); //remove infeasible prime paths from prime path list //only if primePaths String is not empty nor null if(!infeasiblePrimePaths.equals("") && !infeasiblePrimePaths.equals(" ") && !infeasiblePrimePaths.equals(null)){ infeasiblePrimePathsString = infeasiblePrimePaths.trim().split(","); //remove the paths from back to the front for(int i = primePaths.size() - 1; i >= 0; i--){ for(int j = 0; j < infeasiblePrimePathsString.length; j++){ // subtract 1 because user input number starting from 1 rather than 0 Integer tempInt = new Integer(infeasiblePrimePathsString[j]) - 1; //remove the infeasible prime path and add a prime path that tours that infeasible prime path with sidetrips if(tempInt.intValue() == i) { Path tempPath = primePaths.get(i); primePaths.remove(i); //remove an infeasible path from primePathsCopy to ensure that only feasible and userful prime paths are left primePathsCopy.remove(i); //put a test path that tours tempPath with sidetrips to the primePaths //for each infeasible path in tempPath, try to find one path that can tour it with sidetrips for(int z = 0;z < tempPath.size();z++){ //use primePathsCopy rather than primePaths to make sure that no prime paths with sidetrips are included in primePaths for(int k = 0; k < primePathsCopy.size();k++){ Path firstPartTempPath = null, secondPartTempPath = null; Path tempPrimePath = primePathsCopy.get(k); //for one node in the infeasible path, check if there exists a feasible prime path whose both first and last node are the same as it //if they are the same, create a one new path that tours the infeasible prime path with sidetrips //and add it to the prime paths list if(tempPath.get(z).equals(tempPrimePath.get(0)) && tempPath.get(z).equals(tempPrimePath.getEnd()) && !tempPath.equals(tempPrimePath)) { if(z == 0) { secondPartTempPath = tempPath.subPath(z+1, tempPath.size()); firstPartTempPath = tempPath.subPath(0, z); firstPartTempPath.extendPath(tempPrimePath.subPath(1, tempPrimePath.size())); firstPartTempPath.extendPath(secondPartTempPath); } else if(z > 0 ) { secondPartTempPath = tempPath.subPath(z, tempPath.size()); firstPartTempPath = tempPath.subPath(0, z); firstPartTempPath.extendPath(tempPrimePath.subPath(0, tempPrimePath.size()-1)); firstPartTempPath.extendPath(secondPartTempPath); } /* else if(z > 0 && tempPath.size() == 3) { secondPartTempPath = tempPath.subPath(z, tempPath.size()); firstPartTempPath = tempPath.subPath(0, z); firstPartTempPath.extendPath(tempPrimePath.subPath(0,tempPrimePath.size())); Path path1 = tempPath.subPath(z+1, tempPath.size()); firstPartTempPath.extendPath(secondPartTempPath); }*/ if(firstPartTempPath.size() < 100) primePaths.add(firstPartTempPath); }//end if }//end for loop of variable k }//end for loop of variable z }//end if }//end for loop of variable j }//end for loop of varialbe i }//end if return primePaths; } /** * Effects: return a path list of prime paths with sidetrips but no marked infeasible prime paths */ public List findPrimePathsWithSidetrips(String infeasiblePrimePaths) { List simplePaths = findSimplePaths(); //sort list in term of the size of path quickSort(simplePaths, 1, simplePaths.size()); List primePaths = new ArrayList(); primePaths.add(simplePaths.get(simplePaths.size()-1)); for(int i = simplePaths.size()-2;i >- 1;i--) { boolean isSubpath = false; for(int j = 0;j < primePaths.size();j++) if(simplePaths.get(i).isSubpath(primePaths.get(j))) { isSubpath = true; break; } if(!isSubpath) primePaths.add(simplePaths.get(i)); } List primePathsCopy = new ArrayList(primePaths.size()); //remove infeasible prime paths from prime path list //only if primePaths String is not empty nor null if(!infeasiblePrimePaths.equals("") && !infeasiblePrimePaths.equals(" ") && !infeasiblePrimePaths.equals(null)){ infeasiblePrimePathsString = infeasiblePrimePaths.trim().split(","); //remove the paths from back to the front for(int i = primePaths.size() - 1; i >= 0; i--){ for(int j = 0; j < infeasiblePrimePathsString.length; j++){ // subtract 1 because user input number starting from 1 rather than 0 Integer tempInt = new Integer(infeasiblePrimePathsString[j]) -1; //remove the infeasible prime path and add a prime path that tours that infeasible prime path with sidetrips if(tempInt.intValue() == i) { Path tempPath = primePaths.get(i); primePaths.remove(i); //put a test path that tours tempPath with sidetrips to the primePaths for(int z = 0;z < tempPath.size();z++){ Path firstPartTempPath = null, secondPartTempPath = null; for(int k = 0; k < primePaths.size();k++){ Path tempPrimePath = primePaths.get(k); //check the current node of this prime path is same as the initial and final node of another prime path if(tempPath.get(z).equals(tempPrimePath.get(0)) && tempPath.get(z).equals(tempPrimePath.getEnd()) && !tempPath.equals(tempPrimePath)) { //final path: firstPartTempPath extends tempPrimePath and also extends secondPartTempPath //secondPartTempPath = tempPath.subPath(z+1, tempPath.size()); secondPartTempPath = tempPath.subPath(z, tempPath.size()); if(z == 0) { firstPartTempPath = tempPath.subPath(0, z); firstPartTempPath.extendPath(tempPrimePath.subPath(1, tempPrimePath.size())); firstPartTempPath.extendPath(secondPartTempPath); } else if(z > 0) { firstPartTempPath = tempPath.subPath(0, z); //firstPartTempPath.extendPath(tempPrimePath); firstPartTempPath.extendPath(tempPrimePath.subPath(0, tempPrimePath.size()-1)); firstPartTempPath.extendPath(secondPartTempPath); } if(firstPartTempPath != null) primePathsCopy.add(i, tempPath); }//end if }//end for loop of variable k }//end for loop of variable z }//end if }//end for loop of variable j }//end for loop of varialbe i }//end if //take care the case when no infeasible prime path else if(infeasiblePrimePaths.equals("")||infeasiblePrimePaths.equals(" ")){ //for a prime path 'i', check other prime paths to see if this prime path can be toured by a test path with sidetrips for(int i = 0; i < primePaths.size(); i++){ Path tempPath = primePaths.get(i); //iterate each node of this prime path for(int z = 0;z < tempPath.size();z++){ Path firstPartTempPath = null, secondPartTempPath = null; //iterate other prime paths for(int k = 0; k < primePaths.size();k++){ Path tempPrimePath = primePaths.get(k); //check the current node of this prime path is same as the initial and final node of another prime path if(tempPath.get(z).equals(tempPrimePath.get(0)) && tempPath.get(z).equals(tempPrimePath.getEnd()) && !tempPath.equals(tempPrimePath)) { //final path: firstPartTempPath extends tempPrimePath and also extends secondPartTempPath secondPartTempPath = tempPath.subPath(z, tempPath.size()); if(z == 0) { firstPartTempPath = tempPath.subPath(0, z); firstPartTempPath.extendPath(tempPrimePath.subPath(1, tempPrimePath.size())); firstPartTempPath.extendPath(secondPartTempPath); } else if(z > 0) { firstPartTempPath = tempPath.subPath(0, z); firstPartTempPath.extendPath(tempPrimePath.subPath(0, tempPrimePath.size()-1)); firstPartTempPath.extendPath(secondPartTempPath); } primePathsCopy.add(i, firstPartTempPath); //primePathsCopy.add(tempPath); }//end if }//end for loop of variable k }//end for loop of variable z }//end for loop of varialbe i }//end if return primePathsCopy; } /* * Effects: return edge-pair requirements of a graph without marked infeasible edge-pairs */ public List findEdgePairs(String infeasibleEdgePairs){ List edgesPath = new ArrayList(); //for each edge, if its destination node has an outgoing edge //add this outgoing edge to it for (int i = 0; i < edges.size(); i++) { if(edges.get(i).dest.sizeOfOutEdges() != 0) { Iterator ie = edges.get(i).dest.getOutGoingIterator(); while(ie.hasNext()){ Path p = new Path(edges.get(i)); Path p1 = new Path(ie.next().dest); p.extendPath(p1); edgesPath.add(p); } } //cover edges that are not covered by paths of length of 2 else if(edges.get(i).dest.sizeOfOutEdges() == 0 && starts.indexOf(edges.get(i).src) != -1) { Path p = new Path(edges.get(i)); edgesPath.add(p); } } /* //remove infeasible prime paths from prime path list //only if primePaths String is not empty nor null if(!infeasibleEdgePairs.equals("") && !infeasibleEdgePairs.equals(" ") && !infeasibleEdgePairs.equals(null)){ infeasibleEdgePairsString = infeasibleEdgePairs.trim().split(","); for(int i = edgesPath.size() - 1; i >= 0; i--){ for(int j = 0; j < infeasibleEdgePairsString.length; j++){ Integer tempInt = new Integer(infeasibleEdgePairsString[j]); if(tempInt.intValue() == i) edgesPath.remove(i); } } } */ //get a copy of prime paths List edgePairsCopy = new ArrayList(); for(int i = 0; i < edgesPath.size();i++) edgePairsCopy.add(edgesPath.get(i)); //remove infeasible edge pairs from edge pairs list //only if edge pairs String is not empty nor null if(!infeasibleEdgePairs.equals("") && !infeasibleEdgePairs.equals(" ") && !infeasibleEdgePairs.equals(null)){ infeasibleEdgePairsString = infeasibleEdgePairs.trim().split(","); //remove the paths from back to the front for(int i = edgesPath.size() - 1; i >= 0; i--){ for(int j = 0; j < infeasibleEdgePairsString.length; j++){ // subtract 1 because user input number starting from 1 rather than 0 Integer tempInt = new Integer(infeasibleEdgePairsString[j]) - 1; //remove the infeasible prime path and add a prime path that tours that infeasible edge pairs with sidetrips if(tempInt.intValue() == i) { Path tempPath = edgesPath.get(i); edgesPath.remove(i); //remove an infeasible path from edgePairsCopy to ensure that only feasible and userful edge pairs are left edgePairsCopy.remove(i); //put a test path that tours tempPath with sidetrips to the edgePairs for(int z = 0;z < tempPath.size();z++){ //use edgePairsCopy rather than edgePairs to make sure that no prime paths with sidetrips are included in edgePairs for(int k = 0; k < edgePairsCopy.size();k++){ Path firstPartTempPath = null, secondPartTempPath = null; Path tempPrimePath = edgePairsCopy.get(k); if(tempPath.get(z).equals(tempPrimePath.get(0)) && tempPath.get(z).equals(tempPrimePath.getEnd()) && !tempPath.equals(tempPrimePath)) { if(z == 0) { secondPartTempPath = tempPath.subPath(z+1, tempPath.size()); firstPartTempPath = tempPath.subPath(0, z); firstPartTempPath.extendPath(tempPrimePath.subPath(1, tempPrimePath.size())); firstPartTempPath.extendPath(secondPartTempPath); } else if(z > 0 ) { secondPartTempPath = tempPath.subPath(z, tempPath.size()); firstPartTempPath = tempPath.subPath(0, z); firstPartTempPath.extendPath(tempPrimePath.subPath(0, tempPrimePath.size()-1)); firstPartTempPath.extendPath(secondPartTempPath); } /* else if(z > 0 && tempPath.size() == 3) { secondPartTempPath = tempPath.subPath(z, tempPath.size()); firstPartTempPath = tempPath.subPath(0, z); firstPartTempPath.extendPath(tempPrimePath.subPath(0,tempPrimePath.size())); Path path1 = tempPath.subPath(z+1, tempPath.size()); firstPartTempPath.extendPath(secondPartTempPath); }*/ if(firstPartTempPath.size() < 100) edgesPath.add(firstPartTempPath); }//end if }//end for loop of variable k }//end for loop of variable z }//end if }//end for loop of variable j }//end for loop of varialbe i }//end if return edgesPath; } /** * @author nli1 * @return a minimum test path that covers all prime paths * This algorithm uses the shortest superstring via set cover */ public List findMinimumPrimePathCoverageViaSetCover(List listOfPaths){ //get the prime paths List primePathsList = new ArrayList(); primePathsList = listOfPaths; //initialize the a list of paths for the set of overlapping paths List overlappingPaths = new ArrayList(); //initialize the minimum test path Path minimumPath = new Path(); //Path tempPath = new Path(); //initialize the a list of paths for the set of overlapping paths List finalSet = new ArrayList(); long start1 = System.nanoTime(); //find the set that consists of the path covering any two paths that have overlaps. for(Path pathI: primePathsList){ for(Path pathJ: primePathsList) { //check another path that is not itself if(!pathI.equals(pathJ)){ int index = 0; //jump out of the while loop if index is equal to -1 while(index != -1){ index = pathI.nextIndexOf(pathJ.get(0), index); //start generating the overlapping path if(index != -1){ //a signal for the overlapping boolean signal = true; //System.out.println("path i: " + pathI); //System.out.println("path j: " + pathJ); //System.out.println("INDEX: " + index); //check whether the last k nodes in path i is the same as the first k nodes in path j for(int i = index; i < pathI.size(); i++){ if(i - index >= pathJ.size()){ signal = false; break; } if(!pathI.get(i).equals(pathJ.get(i - index))){ signal = false; break; } }//end of for loop //the last k nodes in path i is the same as the first k nodes in path j, //get the new path that covers two paths i and j if(signal == true){ Path tempPath = pathI.subPath(0, index); //System.out.println("temp path: " + tempPath); tempPath = tempPath.immutableExtendedPath(pathJ); overlappingPaths.add(tempPath); } }//end of if statement }//end of while loop }//end of if statement }//end of for loop }//end of for loop long end1 = System.nanoTime(); long duration1 = end1 - start1; //System.out.println("Time for constructing set covers: " + duration1); long start2 = System.nanoTime(); //add prime paths to the final set for(Path path: primePathsList){ finalSet.add(path); } //add overlapping paths to the final set for(Path path: overlappingPaths){ finalSet.add(path); //System.out.println("super-test requirement for two prime paths " + "#" + overlappingPaths.indexOf(path) + ": "+ path.toString()); } int numberOfSetsSelected = 0; int numberOfSets = finalSet.size(); //initialize the number of prime paths that are the subpaths of one path in the final set List numberOfSubs = new ArrayList(); for(int i = 0 ; i < finalSet.size();i++) numberOfSubs.add(new Integer(0)); //generate the minimum test set while(primePathsList.size() > 0){ double ratio = 100; int index = 0; for(int i = 0; i < finalSet.size(); i++){ //calculate how many prime paths are in one path of final set Integer num = 0; for(Path primePath: primePathsList){ if(finalSet.get(i).indexOf(primePath) != -1){ num++; } } //System.out.println("numberOfSubssize" + numberOfSubs.size()); //System.out.println("i" + i); numberOfSubs.set(i, num); //the following statements are not executed //if no prime paths are the sub paths of this path in the final set if(numberOfSubs.get(i) != 0){ //only keep track of the minimum effect/cost if((finalSet.get(i).size() / numberOfSubs.get(i)) < ratio){ ratio = (double)finalSet.get(i).size() / (double)numberOfSubs.get(i); index = i; } } } for(int i = 0;i < primePathsList.size(); i++){ int index1 = finalSet.get(index).indexOf(primePathsList.get(i)); if(index1 != -1){ primePathsList.remove(i); i--; } } //System.out.println("size of prime paths: " + primePathsList.size()); // System.out.println("extended path: " + finalSet.get(index) + " ;size: " + finalSet.get(index).size()); //tempPath = minimumPath.immutableExtendedPath(finalSet.get(index)); minimumPath.extendPath(finalSet.get(index)); //System.out.println("Selected super-test requirement: " + finalSet.get(index)); numberOfSetsSelected++; // System.out.println("minimumPath: " + minimumPath); finalSet.remove(index); numberOfSubs.remove(index); }//end while loop long end2 = System.nanoTime(); long duration2 = end2 - start2; //System.out.println("Time for greedy algorithm: " + duration2); //System.out.println("final minimumPath: " + minimumPath); //System.out.println("size: " + minimumPath.size()); //System.out.println("number of sets selected: " + numberOfSetsSelected); //System.out.println("number of sets: " + numberOfSets); overlappingPaths.removeAll(overlappingPaths); overlappingPaths.add(minimumPath); return overlappingPaths; } /** * @author nli1 * @return a minimum test path that covers all prime paths * This algorithm uses the shortest superstring via set cover */ public List findMinimumPrimePathCoverageViaPrefixGraph(List listOfPaths){ List minimumPaths = new ArrayList(); Iterator edgesIterator = edges.iterator(); List primePaths = listOfPaths; List leftSide = new ArrayList(); List rightSide = new ArrayList(); Path minimumPath = new Path(); //construct the vertices of left side and of the right side while(edgesIterator.hasNext()){ Edge edge = edgesIterator.next(); boolean signForLeft = true; boolean signForRight = true; for(Node node: leftSide){ if(edge.getSrc().equals(node)) signForLeft = false; } if(signForLeft) leftSide.add(edge.getSrc()); for(Node node: rightSide){ if(edge.getDest().equals(node)) signForRight = false; } if(signForRight) rightSide.add(edge.getDest()); } /* for(int i = 0;i < leftSide.size();i++) System.out.println(leftSide.get(i)); System.out.println("..........."); for(int i = 0;i < rightSide.size();i++) System.out.println(rightSide.get(i)); System.out.println("...........");*/ List perfectMatching = new ArrayList(); Iterator edgesLeft = null; for(int i = 0; i < leftSide.size(); i++){ Node node = leftSide.get(i); edgesLeft = node.getOutGoingIterator(); //size of the outgoing edges for this node int size = node.sizeOfOutEdges(); int counter = 0; //go through all outgoing edges while(edgesLeft.hasNext()){ Edge edge = edgesLeft.next(); counter++; //decide whether this edge is incident to the same node with another edge boolean sign = false; for(int j = 0; j < perfectMatching.size();j++){ if(perfectMatching.get(j).getDest().equals(edge.getDest())){ sign = true; break; } }//end of for loop of variable j if(sign == false){ perfectMatching.add(edge); break; } else{ if(size != counter){ continue; } //if all outgoing edges share a node that is incident to another edge else{ //System.out.println("The thing: " + node + " " + edge); edgesLeft = node.getOutGoingIterator(); outer: while(edgesLeft.hasNext()){ if(i == (perfectMatching.size() - 1)) break; Edge edge1 = edgesLeft.next(); // System.out.println("edge1: " + edge1); Node nodeDest = edge1.getDest(); // System.out.println("edge1's dest " + edge1.getDest()); Node nodeSrc = null; int position = 0; for(int x = 0; x < perfectMatching.size(); x++){ if(perfectMatching.get(x).getDest().equals(nodeDest)){ nodeSrc = perfectMatching.get(x).getSrc(); position = x; break; } } //System.out.println("position " + position); if(nodeSrc != null){ Iterator edges = nodeSrc.getOutGoingIterator(); while(edges.hasNext()){ Edge edge2 = edges.next(); boolean sign1 = false; // System.out.println("edge2: " + edge2); for(int y = 0; y < perfectMatching.size(); y++){ if(edge2.getDest().equals(perfectMatching.get(y).getDest())){ sign1 = true; break; } }//end for loop with variable y if(sign1 == false){ perfectMatching.set(position, edge2); perfectMatching.add(edge1); // System.out.println("edge2: " + edge2 + "edge1: " + edge1); break outer; } }//end while loop }//end if }//end while loop }//end if-else }//end if-else }//end while loop }//end of for loop of variable i // for(int i = 0;i < perfectMatching.size();i++){ // System.out.println(perfectMatching.get(i)); // } List paths = null; //System.out.println(result); // for(Edge edge: perfectMatching) // System.out.print(edge); Path path = new Path(); paths = new ArrayList(); boolean signForMatching = false; path.extendPath(perfectMatching.get(0).getSrc()); path.extendPath(perfectMatching.get(0).getDest()); perfectMatching.remove(0); while(perfectMatching.size() > 0){ if(path.size() == 0){ path.extendPath(perfectMatching.get(0).getSrc()); path.extendPath(perfectMatching.get(0).getDest()); perfectMatching.remove(0);; } signForMatching = false; // System.out.print("path: " + path); for(int y = 0; y < perfectMatching.size(); y++){ if(path.get(0).equals(perfectMatching.get(y).getDest())){ Path p = new Path(); p.extendPath(perfectMatching.get(y).getSrc()); p.extendPath(path); path = new Path(); path = p; perfectMatching.remove(y); // System.out.print("pathdest: " + path + "size: " + perfectMatching.size()); if(perfectMatching.size() == 0){ paths.add(path); path = new Path(); } y--; signForMatching = true; break; } if(path.getEnd().equals(perfectMatching.get(y).getSrc())){ path.extendPath(perfectMatching.get(y).getDest()); perfectMatching.remove(y); // System.out.print("pathsrc: " + path + "size: " + perfectMatching.size()); if(perfectMatching.size() == 0){ paths.add(path); path = new Path(); } y--; signForMatching = true; break; } }//end for loop if(signForMatching != true){ //if(path.size() == 2){ paths.add(path); //} path = new Path(); } }//end while loop // System.out.println(); int tempValue = 0; for(Path path1: paths){ //System.out.println("finalpath: " + path1); path = new Path(); List nodes = path1.path; for(int m = 0; m < nodes.size() - 1; m++){ Node nSrc = nodes.get(m); Node nDest = nodes.get(m + 1); Edge e = new Edge(nSrc, nDest); boolean signForEdge = false; for(int l = 0; l < edges.size(); l++){ if(e.equals(edges.get(l))){ tempValue = tempValue + ((Path)edges.get(l).getWeight()).size(); path.extendPath((Path)edges.get(l).getWeight()); signForEdge = true; } }//end for loop if(m == nodes.size() - 2){ tempValue = tempValue + ((Path)nodes.get(m + 1).getObject()).size(); path.extendPath((Path)nodes.get(m + 1).getObject()); } }//end for loop minimumPath.extendPath(path); //System.out.println("minimumpath: " + minimumPath); }//end for loop for(Path path1: primePaths){ //System.out.println("path: " + path1); if(minimumPath.indexOf(path1) == -1) minimumPath.extendPath(path1); } //System.out.println("minimumpath: " + minimumPath); minimumPaths.add(minimumPath); return minimumPaths; } /** * @author nli1 * @return a minimum test path that covers all prime paths * This algorithm uses the shortest superstring via set cover * @throws InvalidGraphException */ public List findMinimumPrimePathCoverageViaPrefixGraphOptimized(List listOfPaths) throws InvalidGraphException{ //a list of paths to be returned List minimumPaths = new ArrayList(); //get the edges of the bipartite graph Iterator edgesIterator = edges.iterator(); //get the prime paths from the formal parameter listOfPaths List primePaths = listOfPaths; //a set for the greedy algorithm in the last step List finalPathsSet = new ArrayList(); //a list of nodes to store the nodes on the left side List leftSide = new ArrayList(); //a list of nodes to store the nodes on the right side List rightSide = new ArrayList(); //the minimum path Path minimumPath = new Path(); //construct vertices on the left side and on the right side while(edgesIterator.hasNext()){ Edge edge = edgesIterator.next(); //a sign for redundant vertices of the left side boolean signForLeft = true; //a sign for redundant vertices of the right side boolean signForRight = true; //if the source node of an edge is not on the list of the left side, add it to the left side for(Node node: leftSide){ if(edge.getSrc().equals(node)) signForLeft = false; } if(signForLeft) leftSide.add(edge.getSrc()); //if the destination node of an edge is not on the list of the left side, add it to the right side for(Node node: rightSide){ if(edge.getDest().equals(node)) signForRight = false; } if(signForRight) rightSide.add(edge.getDest()); } long start1 = System.nanoTime(); //a list of edges to store the perfect matching List perfectMatching = new ArrayList(); int counterOne = 0; int counterTwo = 0; //an iterator of edges for each vertex on the left side Iterator edgesLeft = null; for(int i = 0; i < leftSide.size(); i++){ //if the vertices of the right side are fewer than those of the left side //and the number of edges in the perfect matching is bigger than the number of vertices of the right side //break from the for loop since the perfect matching has been completed if(perfectMatching.size() >= rightSide.size() && rightSide.size() < leftSide.size()) break; // System.out.println("i: "+ i); //get the iterator of edges for one vertex Node node = leftSide.get(i); edgesLeft = node.getOutGoingIterator(); //size of the outgoing edges for this vertex int size = node.sizeOfOutEdges(); int counter = 0; //go through all outgoing edges while(edgesLeft.hasNext()){ Edge edge = edgesLeft.next(); counter++; //decide whether this edge is incident to the same vertex with another edge boolean sign = false; for(int j = 0; j < perfectMatching.size();j++){ if(perfectMatching.get(j).getDest().equals(edge.getDest())){ sign = true; break; } }//end of for loop of variable j //if the destination node of this edge has not been in any other matchings that have been selected for the perfect matching //add this edge to the perfect matching if(sign == false){ perfectMatching.add(edge); //jump out of the loop and go to the next vertex break; } //if the destination node of this edge has been in any other matchings that have been selected for the perfect matching //switch the edge with another edge that has been selected else{ //try the next edge if this edge is not the last one for this vertex if(size != counter){ continue; } //if each outgoing edge shares a node that is incident to another edge that has been in the matchings else{ edgesLeft = node.getOutGoingIterator(); boolean signForSwitch = false; // check if the edge have been switched with another //go through all edges for this vertex outer: while(edgesLeft.hasNext()){ if(i == (perfectMatching.size() - 1)) break; Edge edge1 = edgesLeft.next(); Node nodeDest = edge1.getDest(); Node nodeSrc = null; int position = 0; //System.out.println("one edge1: " + edge1); counterOne++; //find the edge that has conflict with the current edge in the perfect matching for(int x = 0; x < perfectMatching.size(); x++){ if(perfectMatching.get(x).getDest().equals(nodeDest)){ //find the vertex that is the source node of the edge that conflicts nodeSrc = perfectMatching.get(x).getSrc(); position = x; break; } } if(nodeSrc != null){ Iterator edges = nodeSrc.getOutGoingIterator(); while(edges.hasNext()){ Edge edge2 = edges.next(); //System.out.println("one edge2: " + edge2); counterTwo++; boolean sign1 = false; //see whether the edge has any conflict with the current perfect matching for(int y = 0; y < perfectMatching.size(); y++){ if(edge2.getDest().equals(perfectMatching.get(y).getDest())){ sign1 = true; break; } }//end for loop with variable y //if no conflicts, add the edges if(sign1 == false){ perfectMatching.set(position, edge2); perfectMatching.add(edge1); signForSwitch = true; break outer; } }//end while loop }//end if }//end while loop //System.out.println("sign: " + signForSwitch); if(signForSwitch == false) break; }//end if-else }//end if-else }//end while loop }//end of for loop of variable i /* for(int i = 0;i < leftSide.size();i++) System.out.println(leftSide.get(i)); System.out.println("..........."); for(int i = 0;i < rightSide.size();i++) System.out.println(rightSide.get(i)); System.out.println("..........."); for(Edge edge: perfectMatching) System.out.println(edge);*/ int sizeOfPerfectMatching = perfectMatching.size(); List paths =new ArrayList(); // for the perfect matching, find the all cycle covers and store all paths to the finalPathsSet Path path = new Path(); boolean signForMatching = false; if(perfectMatching.size() >= 1){ path.extendPath(perfectMatching.get(0).getSrc()); path.extendPath(perfectMatching.get(0).getDest()); perfectMatching.remove(0); } while(perfectMatching.size() > 0){ if(path.size() == 0){ path.extendPath(perfectMatching.get(0).getSrc()); path.extendPath(perfectMatching.get(0).getDest()); perfectMatching.remove(0);; } signForMatching = false; for(int y = 0; y < perfectMatching.size(); y++){ //if the first node of the path is the same as the last node of one path in the perfect matching if(path.get(0).equals(perfectMatching.get(y).getDest())){ Path p = new Path(); p.extendPath(perfectMatching.get(y).getSrc()); p.extendPath(path); path = new Path(); path = p; perfectMatching.remove(y); if(perfectMatching.size() == 0){ paths.add(path); path = new Path(); } y--; signForMatching = true; break; } //if the last node of the path is the same as the first node of one path in the perfect matching if(path.getEnd().equals(perfectMatching.get(y).getSrc())){ path.extendPath(perfectMatching.get(y).getDest()); perfectMatching.remove(y); if(perfectMatching.size() == 0){ paths.add(path); path = new Path(); } y--; signForMatching = true; break; } }//end for loop // if the current path does not have any overlapping with any path in the perfect matchings, add this path to paths if(signForMatching != true){ paths.add(path); path = new Path(); } }//end while loop //int tempValue = 0; for(Path path1: paths){ // System.out.println("finalpath: " + path1); path = new Path(); List nodes = path1.path; boolean sign = false; if(nodes.get(0).equals(nodes.get(nodes.size() - 1))){ sign = true; } int size = nodes.size(); for(int m = 0; m < size - 1; m++){ Node nSrc = nodes.get(m); Node nDest = nodes.get(m + 1); Edge e = new Edge(nSrc, nDest); // boolean signForEdge = false; for(int l = 0; l < edges.size(); l++){ if(e.equals(edges.get(l))){ //tempValue = tempValue + ((Path)edges.get(l).getWeight()).size(); path.extendPath((Path)edges.get(l).getWeight()); // signForEdge = true; } }//end for loop if(m == size - 2 && sign == false){ //tempValue = tempValue + ((Path)nodes.get(m + 1).getObject()).size(); path.extendPath((Path)nodes.get(m + 1).getObject()); } if(m == size - 3 && sign == true){ path.extendPath((Path)nodes.get(m + 1).getObject()); break; } }//end for loop of variable m // System.out.println("path: " + path); minimumPath.extendPath(path); finalPathsSet.add(path); // System.out.println("minimumpath: " + minimumPath); }//end for loop // System.out.println("middle minimumPath: " + minimumPath + "; size: " + minimumPath.size()); long end1 = System.nanoTime(); long duration1 = end1 - start1; //System.out.println("Time for constructing cycle covers: " + duration1); long start2 = System.nanoTime(); //add prime paths to the final paths set minimumPath = new Path(); for(Path tempPath: primePaths){ finalPathsSet.add(tempPath); } int numberOfFinalSets = finalPathsSet.size(); int numberOfSetsSelected = 0; //run the greedy algorithm //initialize the number of prime paths that are the subpaths of one path in the final set List numberOfSubs = new ArrayList(); for(int i = 0 ; i < finalPathsSet.size();i++) numberOfSubs.add(new Integer(0)); //generate the minimum test set while(primePaths.size() > 0){ // if(finalPathsSet.size() == 0) // break; double ratio = 100; int index = 0; for(int i = 0; i < finalPathsSet.size(); i++){ //calculate how many prime paths are in one path of final set Integer num = 0; for(Path primePath: primePaths){ if(finalPathsSet.get(i).indexOf(primePath) != -1){ num++; } } //System.out.println("numberOfSubssize" + numberOfSubs.size()); //System.out.println("i" + i); numberOfSubs.set(i, num); //the following statements are not executed //if no prime paths are the sub paths of this path in the final set if(numberOfSubs.get(i) != 0){ //only keep track of the minimum effect/cost if((finalPathsSet.get(i).size() / numberOfSubs.get(i)) < ratio){ ratio = (double)finalPathsSet.get(i).size() / (double)numberOfSubs.get(i); index = i; } } } for(int i = 0;i < primePaths.size(); i++){ // System.out.println("index: " + index); // System.out.println("size: " + finalPathsSet.size()); int index1 = finalPathsSet.get(index).indexOf(primePaths.get(i)); if(index1 != -1){ primePaths.remove(i); i--; } } //System.out.println("size of prime paths: " + primePathsList.size()); // System.out.println("extended path: " + finalPathsSet.get(index) + " ;size: " + finalPathsSet.get(index).size()); //tempPath = minimumPath.immutableExtendedPath(finalSet.get(index)); minimumPath.extendPath(finalPathsSet.get(index)); numberOfSetsSelected++; // System.out.println("minimumPath: " + minimumPath); finalPathsSet.remove(index); numberOfSubs.remove(index); }//end while loop long end2 = System.nanoTime(); long duration2 = end2 - start2; //System.out.println("Time for greedy algorithm: " + duration2); /* for(Path path1: primePaths){ if(minimumPath.indexOf(path1) == -1) minimumPath.extendPath(path1); }*/ //System.out.println("final minimumpath: " + minimumPath); //System.out.println("length: " + minimumPath.size()); /* System.out.println("number of sets selected: " + numberOfSetsSelected); System.out.println("number of sets: " + numberOfFinalSets); System.out.println("left side size: " + leftSide.size()); System.out.println("right side size: " + rightSide.size()); System.out.println("perfect matching: " + sizeOfPerfectMatching); System.out.println("edge1: " + counterOne); System.out.println("edge2: " + counterTwo);*/ minimumPaths.add(minimumPath); return minimumPaths; } public List splittedPathsFromSuperString(Path superString, List testPaths){ // System.out.println("super string: " + superString.toString()); /* System.out.println("-----test paths------"); for(Path path: testPaths){ System.out.println(path.toString()); } System.out.println("-----test paths------");*/ long start = System.nanoTime(); /* * Breaking a long superstring into shorter test paths starts here: * */ List paths = new ArrayList(); // System.out.println("size of starts: " + starts.size()); //List localTestPaths = testPaths; Path testPath = new Path(superString.get(0)); for(int i = 1; i < superString.size();i++){ Node node = superString.get(i); //if the preceding node is not connected to this node, create a new test path starting from //this node if(isInitialNode(node) && !isEdge(superString.get(i - 1), node)){ testPath = new Path(node); } else if(testPath == null){ testPath = new Path(node); } else{ testPath.extendPath(node); } //System.out.println("first: " + testPath); //check whether the current path has been disconnected from the adjacent nodes in the minimumPath if(i == superString.size() - 1){ if(!isInitialNode(testPath.get(0))){ //find the smallest index of the node in each existing test path int indexInt = 32255; int index = 0; for(int j = 0;j < testPaths.size();j++){ if(testPaths.get(j).indexOf(testPath.get(0)) < indexInt && testPaths.get(j).indexOf(testPath.get(0))>= 0 ){ indexInt = testPaths.get(j).indexOf(testPath.get(0)); index = j; } } //construct a test path by using a starting node from existing test paths Path thePath = new Path(testPaths.get(index).get(0)); for(int j = 1;j < indexInt;j++){ thePath.extendPath(testPaths.get(index).get(j)); } for(int j = 0;j < testPath.size();j++){ thePath.extendPath(testPath.get(j)); } testPath = new Path(); for(int j = 0;j < thePath.size();j++){ testPath.extendPath(thePath.get(j)); } } if(!isEndingNode(testPath.getEnd())){ //find the smallest index of the node in each existing test path int indexInt = 0; int index = 0; for(int j = 0;j < testPaths.size();j++){ if(testPaths.get(j).lastIndexOf(testPath.getEnd()) > indexInt){ indexInt = testPaths.get(j).lastIndexOf(testPath.getEnd()); index = j; } } //this piece of code is commented out because it adds redundant nodes to the very last split test path //a test path should be [1,2,4,6,7,9,10] but this code results in [1,2,4,6,7,9,9,9,10] but no [9,9] exists //construct a test path by using a starting node from existing test paths // Path thePath = new Path(testPaths.get(index).get(indexInt)); // for(int j = indexInt;j < testPaths.get(index).size();j++){ // thePath.extendPath(testPaths.get(index).get(j)); // } for(int j = indexInt + 1;j < testPaths.get(index).size();j++){ testPath.extendPath(testPaths.get(index).get(j)); } } //System.out.println("testPathlast: " + testPath); paths.add(testPath); } //if the current node is not connected to the next node, generate a test path for the previously selected nodes else if(!isEdge(node, superString.get(i + 1))){ if(!isInitialNode(testPath.get(0))){ //find the smallest index of the node in each existing test path int indexInt = 32255; int index = 0; for(int j = 0;j < testPaths.size();j++){ if(testPaths.get(j).indexOf(testPath.get(0)) < indexInt && testPaths.get(j).indexOf(testPath.get(0))>= 0 ){ indexInt = testPaths.get(j).indexOf(testPath.get(0)); index = j; } } //System.out.println("indexInt: " + indexInt); //System.out.println("index: " + index); //construct a test path by using a starting node from existing test paths Path thePath = new Path(testPaths.get(index).get(0)); for(int j = 1;j < indexInt;j++){ thePath.extendPath(testPaths.get(index).get(j)); } for(int j = 0;j < testPath.size();j++){ thePath.extendPath(testPath.get(j)); } //System.out.println("thePath: " + thePath); testPath = new Path(); for(int j = 0;j < thePath.size();j++){ testPath.extendPath(thePath.get(j)); } } if(!isEndingNode(testPath.getEnd())){ //find the smallest index of the node in each existing test path int indexInt = 0; int index = 0; for(int j = 0;j < testPaths.size();j++){ if(testPaths.get(j).lastIndexOf(testPath.getEnd()) > indexInt){ indexInt = testPaths.get(j).lastIndexOf(testPath.getEnd()); index = j; } } // System.out.println("indexInt: " + indexInt); // System.out.println("index: " + index); //construct a test path by using a starting node from existing test paths Path thePath = new Path(testPaths.get(index).get(indexInt + 1)); for(int j = indexInt + 2;j < testPaths.get(index).size();j++){ thePath.extendPath(testPaths.get(index).get(j)); } for(int j = 0;j < thePath.size();j++){ testPath.extendPath(thePath.get(j)); } } // System.out.println("testPath: " + testPath); paths.add(testPath); // System.out.println("testPath: " + testPath); testPath = null; } /* else{ if(!isInitialNode(testPath.get(0))){ //find the smallest index of the node in each existing test path int indexInt = 32255; int index = 0; for(int j = 0;j < testPaths.size();j++){ if(testPaths.get(j).indexOf(testPath.get(0)) < indexInt && testPaths.get(j).indexOf(testPath.get(0))>= 0 ){ indexInt = testPaths.get(j).indexOf(testPath.get(0)); index = j; } } //construct a test path by using a starting node from existing test paths Path thePath = new Path(testPaths.get(index).get(0)); for(int j = 1;j < indexInt;j++){ thePath.extendPath(testPaths.get(index).get(j)); } for(int j = 0;j < testPath.size();j++){ thePath.extendPath(testPath.get(j)); } testPath = new Path(); for(int j = 0;j < thePath.size();j++){ testPath.extendPath(thePath.get(j)); } } if(!isEndingNode(testPath.getEnd())){ //find the smallest index of the node in each existing test path int indexInt = 0; int index = 0; for(int j = 0;j < testPaths.size();j++){ if(testPaths.get(j).lastIndexOf(testPath.getEnd()) > indexInt){ indexInt = testPaths.get(j).lastIndexOf(testPath.getEnd()); index = j; } } //construct a test path by using a starting node from existing test paths Path thePath = new Path(testPaths.get(index).get(indexInt)); for(int j = indexInt;j < testPaths.get(index).size();j++){ thePath.extendPath(testPaths.get(index).get(j)); } for(int j = 0;j < thePath.size();j++){ testPath.extendPath(thePath.get(j)); } } System.out.println("testPath: " + testPath); paths.add(testPath); } */ }//end for loop //remove duplicated paths in the path list for(int i = 0; i < paths.size(); i++){ Path path = paths.get(i); for(int j = i + 1; j < paths.size(); ){ Path anotherPath = paths.get(j); if(path.equals(anotherPath)){ paths.remove(j); } else{ j++; } } } long end = System.nanoTime(); long duration = end - start; //System.out.println("running time of splitting super string = " + duration); return paths; } /** * * @param starting * @param target * @return a list of all augmenting paths * @throws InvalidGraphException */ public List fordFulkerson(Node starting, Node target) throws InvalidGraphException{ List augmentingPaths = new ArrayList(); //a residual graph Graph residualGraph = new Graph(); //create a residual graph having the same nodes and edges as the original graph for(Node node: this.nodes){ residualGraph.createNode(node.getObject()); } //assign the capacities for all edges /* List edges = this.edges; edges.get(0).setCapacity(16); edges.get(1).setCapacity(13); edges.get(2).setCapacity(12); edges.get(3).setCapacity(4); edges.get(4).setCapacity(14); edges.get(5).setCapacity(9); edges.get(6).setCapacity(20); edges.get(7).setCapacity(7); edges.get(8).setCapacity(4);*/ //System.out.println("flow graph edges: " + this.edges.size()); //add edges between left side and right side for(Edge edge: this.edges){ Node leftNode = edge.src; Node rightNode = edge.dest; for(Node node: residualGraph.nodes){ if(!node.getObject().equals("S") && !node.getObject().equals("T")){ if(((Path)node.getObject()).equals(leftNode.getObject())) leftNode = node; if(((Path)node.getObject()).equals(rightNode.getObject())) rightNode = node; } } residualGraph.createEdge(leftNode, rightNode, null, edge.getCapacity(), edge.getFlow()); } //add the starting and final node if(starting != null) residualGraph.starts.add(starting); else{ for(Node node: this.starts) residualGraph.addInitialNode(residualGraph.createNode(node.getObject())); } if(target != null) residualGraph.ends.add(target); else{ for(Node node: this.ends) residualGraph.addEndingNode(residualGraph.createNode(node.getObject())); } // for(Node node: residualGraph.nodes) // System.out.println(node.toString()); //System.out.println("residual graph edges: " + residualGraph.edges.size()); //for(Edge edge: residualGraph.edges) // System.out.println(edge.toStringWithFlow()); Path augmentingPath = null; //System.out.println("nodes' size: " + residualGraph.nodes.size()); int numberLeft = 0; int numberRight = 0; int numberForStop = 0; for(int i = 0; i < nodes.size();i++){ if(!ends.contains(nodes.get(i))){ if(nodes.get(i).toString().indexOf("L") != -1) numberLeft++; if(nodes.get(i).toString().indexOf("R") != -1) numberRight++; } } if(numberLeft < numberRight) numberForStop = numberLeft; else numberForStop = numberRight; while((augmentingPath = residualGraph.nextAugmentingPath()) != null || augmentingPaths.size() < numberForStop){ //if(augmentingPaths == null) // break; augmentingPaths.add(augmentingPath); //get all edges from the augmenting path List edgesOfAugmentingPath = new ArrayList(); for(int i = 0; i < augmentingPath.size();){ Edge edge = residualGraph.findEdge(augmentingPath.get(i).getObject(), augmentingPath.get(++i).getObject()); edgesOfAugmentingPath.add(edge); //jump out of the loop if all edges are reached if(i == (augmentingPath.size() - 1)) break; } //get the minimum flow for the augmenting path int minimumFlow = 200000; for(Edge edge:edgesOfAugmentingPath){ //System.out.println("edge: " + edge.toString()); if(edge.getCapacity() < minimumFlow) minimumFlow = edge.getCapacity(); } //update the flows in the flow graph for(Edge edge: this.edges){ for(Edge edge1: edgesOfAugmentingPath){ if(edge.equals(edge1) && (edge.getCapacity() >= edge.getFlow() + minimumFlow)) edge.setFlow(edge.getFlow() + minimumFlow); } } //update the residual graph for(Edge edge: edgesOfAugmentingPath){ // for(Edge edge1: residualGraph.edges){ // if(edge.equals(edge1)){ if(minimumFlow < edge.getCapacity()){ edge.setCapacity(edge.getCapacity() - minimumFlow); if(residualGraph.findEdge(edge.dest.getObject(), edge.src.getObject()) == null) residualGraph.addEdge(new Edge(residualGraph.createNode(edge.dest.getObject()), residualGraph.createNode(edge.src.getObject()), null, minimumFlow, 0)); else residualGraph.findEdge(edge.dest.getObject(), edge.src.getObject()).setCapacity(residualGraph.findEdge(edge.dest.getObject(), edge.src.getObject()).getCapacity() + minimumFlow); } else if(minimumFlow == edge.getCapacity()){ residualGraph.edges.remove(edge); residualGraph.findNode(edge.src.getObject()).removeOutGoing(edge); if(residualGraph.findEdge(edge.dest.getObject(), edge.src.getObject()) == null) residualGraph.addEdge(new Edge(residualGraph.createNode(edge.dest.getObject()), residualGraph.createNode(edge.src.getObject()), null, minimumFlow, 0)); else residualGraph.findEdge(edge.dest.getObject(), edge.src.getObject()).setCapacity(residualGraph.findEdge(edge.dest.getObject(), edge.src.getObject()).getCapacity() + minimumFlow); } // } // } } //for(Edge edge: this.edges) // System.out.println("flow edges: " + edge.toStringWithFlow()); //System.out.println("----------------------------------------------------"); //for(Edge edge: residualGraph.edges) // System.out.println("residual edges: " + edge.toStringWithFlow()); } return augmentingPaths; } /** * * @return the next augmenting path from the residual graph * @throws InvalidGraphException */ public Path nextAugmentingPath() throws InvalidGraphException{ //validate whether the graph is valid // validate(); //create result to return the expected paths List result = new ArrayList(); //compute the possible number for the paths /* long possibleNumber = 1L; for(int i = 0; i < nodes.size();i++){ if(!ends.contains(nodes.get(i))){ System.out.println(nodes.get(i)); System.out.println(nodes.get(i).sizeOfOutEdges()); possibleNumber *= nodes.get(i).sizeOfOutEdges(); } } System.out.println("possibleNumber: " + possibleNumber);*/ //go through all paths from each initial node // for(int j = 0; j < starts.size();j++) { //add all nodes to nodesCopy List nodesCopy = new ArrayList(); for(int i = 0;i < nodes.size();i++) nodesCopy.add(nodes.get(i)); //remove all initial nodes from nodesCopy for(int i = starts.size() - 1;i >= 0;i--) { int index = nodes.indexOf(starts.get(i)); nodesCopy.remove(index); } //initialize each path with one initial node List paths = new ArrayList(); paths.add(new Path(starts.get(j))); //for(Edge edge: edges){ // System.out.println("edge: " + edge.toStringWithFlow()); //} //create paths //get paths from one initial node //paths starts from an initial node, keep expanding itself, and check if all nodes except initial nodes have been reached //put paths into result if the corresponding node has been reached //stop while looping when all paths have been removed from paths, which means all nodes have been reached in a graph while(paths.size() != 0) { //from each initial node, go through each possible path for(int i = 0;i < paths.size();i++) { Path path = paths.get(i); Node end = path.getEnd(); Iterator outEdges = end.getOutGoingIterator(); int count = 0; while(outEdges.hasNext()) { count++; //if the edge is the last edge to go through if(count == end.sizeOfOutEdges()) path.extendPath(outEdges.next().getDest());//extend path itself else { Path newPath = (Path)path.clone();//copy path and extend the copy newPath.extendPath(outEdges.next().getDest()); paths.add(i+1, newPath); i++;//add one to variable i to avoid keep looping in the for loop }//end if-else }//end while loop }//end for loop //if(paths.size() > possibleNumber) // return null; //put paths in result when the expected node has been reached for(int i = 0;i < paths.size();i++) { //System.out.println("path " + i + ": " + paths.get(i)); Path path = paths.get(i); Node end = path.getEnd(); //Node start = path.get(0); boolean sign = false; /*for(Node node: starts) if(node.equals(start)){ sign = true; break; } else sign = false;*/ for(Node node: ends){ if(node.equals(end)){ sign = true; break; } } // System.out.println(ends.contains(end) && starts.contains(start)); // System.out.println("sign: " + sign); // System.out.println(starts.get(0).equals(start)); //if a node is just being reached, remove it from nodesCopy if(end.sizeOfOutEdges() <= 0 && sign == false) { paths.remove(i); i--;//subtract one from i to keep looping the paths because one path has been removed from paths } //if a node has been reached, put the path to which the node belongs to result // else if (ends.contains(end) && starts.contains(start)) else if(sign == true) { // System.out.println("path: " + path); paths.remove(i); i--;//subtract one from i to keep looping the paths because one path has been removed from paths result.add(path); return path; } } }//end while loop }//end for loop with variable j return null; } //a quicksort algorithm private void quickSort(List paths, int p, int len) { int pivot = -1; if(p < len) { Path x = paths.get(p); int i = p-1; int j = len; while(true) { j -= 1; for(;true;j--) if(paths.get(j).size()<= x.size()) break; i += 1; for(;true;i ++ ) if(paths.get(i).size() >= x.size()) break; if(i < j) { Path temp = paths.get(i); paths.set(i, paths.get(j)); paths.set(j, temp); }else { pivot = j; break; } } quickSort(paths,p,pivot); quickSort(paths,pivot+1, len); } } /** * * @return true if there is an edge between the two nodes;otherwise, return false */ public boolean isEdge(Node start, Node end){ Iterator ie = start.getOutGoingIterator(); Edge e = null; while(ie.hasNext()){ e = ie.next(); if(e.getDest().equals(end)) return true; } return false; } /** * down cast to DFGraph * * @return */ public DFGraph createDFGraph() { return new DFGraph(nodes, edges, starts, ends); } }