return owner;
}
- public static void computeclosure(Set nodes) {
+ public static void computeclosure(Set nodes, Set removed) {
Stack tovisit=new Stack();
tovisit.addAll(nodes);
while(!tovisit.isEmpty()) {
Edge edge=(Edge)it.next();
GraphNode target=edge.getTarget();
if (!nodes.contains(target)) {
- nodes.add(target);
- tovisit.push(target);
+ if ((removed!=null)&&
+ (!removed.contains(target))) {
+ nodes.add(target);
+ tovisit.push(target);
+ }
}
}
}
}
public void discover(int time) {
- discoverytime = time++;
+ discoverytime = time;
status = PROCESSING;
}
public void finish(int time) {
assert status == PROCESSING;
- finishingtime = time++;
+ finishingtime = time;
status = FINISHED;
}
return finishingtime;
}
+
public static class DOTVisitor {
java.io.PrintWriter output;
output.println("\tremincross=true;");*/
output.println("\tnode [fontsize=10,height=\"0.1\", width=\"0.1\"];");
output.println("\tedge [fontsize=6];");
-
traverse();
-
output.println("}\n");
}
private void traverse() {
+ Set cycleset=GraphNode.findcycles(nodes);
+
Iterator i = nodes.iterator();
while (i.hasNext()) {
GraphNode gn = (GraphNode) i.next();
Iterator edges = gn.edges();
String label = gn.getTextLabel(); // + " [" + gn.discoverytime + "," + gn.finishingtime + "];";
- output.println("\t" + gn.getLabel() + " [label=\"" + label + "\"" + gn.dotnodeparams + "];");
+ String option="";
+ if (cycleset.contains(gn))
+ option=",style=bold";
+ output.println("\t" + gn.getLabel() + " [label=\"" + label + "\"" + gn.dotnodeparams + option+"];");
while (edges.hasNext()) {
Edge edge = (Edge) edges.next();
}
}
}
+
+ /* XXXXXXXX Should use SCC algorithm here - will change */
+ public static Set findcycles(Collection nodes) {
+ Stack st=new Stack();
+ HashSet acyclic=new HashSet();
+ HashSet cycles=new HashSet();
+ for(Iterator it=nodes.iterator();it.hasNext();) {
+ GraphNode node=(GraphNode)it.next();
+ if (acyclic.contains(node))
+ continue;
+ if (cycles.contains(node))
+ continue;
+ findcycles(cycles, acyclic, st,node,nodes);
+ }
+ return cycles;
+ }
+
+ private static boolean findcycles(Set cycles, Set acyclic, Stack visited, GraphNode gn, Collection nodes) {
+ if (visited.contains(gn)) {/* Found cycle */
+ cycles.addAll(visited.subList(visited.indexOf(gn),visited.size())); /* Add this cycle */
+ return true;
+ }
+ boolean acyclicflag=true;
+ visited.push(gn);
+ for(Iterator it=gn.edges();it.hasNext();) {
+ Edge e=(Edge) it.next();
+ GraphNode node = e.getTarget();
+ if (!nodes.contains(node))
+ continue; /* Don't visit stuff outside set */
+ if (acyclic.contains(node))
+ continue;
+ if (findcycles(cycles,acyclic,visited,node,nodes)) {
+ /* Found cycle */
+ acyclicflag=false;
+ }
+ }
+ visited.pop();
+ if (acyclicflag) {
+ acyclic.add(gn); /* no cycles through gn */
+ return false;
+ } else
+ return true; /* found cycle */
+ }
/**
* DFS encapsulates the depth first search algorithm
this.nodes = nodes;
}
- public static void depthFirstSearch(Collection nodes) {
+ public static boolean depthFirstSearch(Collection nodes) {
if (nodes == null) {
throw new NullPointerException();
}
DFS dfs = new DFS(nodes);
- dfs.go();
+ return dfs.go();
}
- private void go() {
+ private boolean go() {
Iterator i;
time = 0;
-
+ boolean acyclic=true;
i = nodes.iterator();
while (i.hasNext()) {
GraphNode gn = (GraphNode) i.next();
i = nodes.iterator();
while (i.hasNext()) {
GraphNode gn = (GraphNode) i.next();
- assert gn.getStatus() != PROCESSING;
+ assert gn.getStatus() != PROCESSING;
if (gn.getStatus() == UNVISITED) {
- dfs(gn);
+ if (!dfs(gn))
+ acyclic=false;
}
}
+ return acyclic;
}
- private void dfs(GraphNode gn) {
+ private boolean dfs(GraphNode gn) {
+ boolean acyclic=true;
gn.discover(time++);
Iterator edges = gn.edges();
while (edges.hasNext()) {
Edge edge = (Edge) edges.next();
GraphNode node = edge.getTarget();
+ if (!nodes.contains(node)) /* Skip nodes which aren't in the set */
+ continue;
if (node.getStatus() == UNVISITED) {
- dfs(node);
- }
+ if (!dfs(node))
+ acyclic=false;
+ } else if (node.getStatus()==PROCESSING) {
+ acyclic=false;
+ }
}
gn.finish(time++);
- }
+ return acyclic;
+ }
} /* end DFS */