Fix node splitting algorithm

This commit is contained in:
Alexey Andreev 2015-03-04 16:43:06 +04:00
parent 043d6f587f
commit 5ea55675f1
2 changed files with 46 additions and 47 deletions

View File

@ -114,45 +114,51 @@ public final class GraphUtils {
int[] headerIndex = new int[graph.size()];
int lastIndex = 0;
IntegerStack stack = new IntegerStack(graph.size());
for (int startNode : start) {
stack.push(startNode);
}
IntegerArray currentComponent = new IntegerArray(1);
while (!stack.isEmpty()) {
int node = stack.pop();
if (visitIndex[node] > 0) {
if (headerIndex[node] > 0) {
continue;
}
currentComponent.add(node);
int hdr = visitIndex[node];
for (int successor : graph.outgoingEdges(node)) {
if (!filter.match(successor)) {
IntegerArray currentComponent = new IntegerArray(1);
while (!stack.isEmpty()) {
int node = stack.pop();
if (visitIndex[node] > 0) {
if (headerIndex[node] > 0) {
continue;
}
if (headerIndex[successor] == 0) {
hdr = Math.min(hdr, visitIndex[successor]);
} else {
hdr = Math.min(hdr, headerIndex[successor]);
currentComponent.add(node);
int hdr = visitIndex[node];
for (int successor : graph.outgoingEdges(node)) {
if (!filter.match(successor)) {
continue;
}
if (headerIndex[successor] == 0) {
hdr = Math.min(hdr, visitIndex[successor]);
} else {
hdr = Math.min(hdr, headerIndex[successor]);
}
}
if (hdr == visitIndex[node]) {
components.add(currentComponent.getAll());
currentComponent.clear();
}
headerIndex[node] = hdr;
} else {
visitIndex[node] = ++lastIndex;
stack.push(node);
for (int successor : graph.outgoingEdges(node)) {
if (!filter.match(successor) || visitIndex[successor] > 0) {
continue;
}
stack.push(successor);
}
}
if (hdr == visitIndex[node]) {
components.add(currentComponent.getAll());
currentComponent.clear();
}
headerIndex[node] = hdr;
} else {
visitIndex[node] = ++lastIndex;
stack.push(node);
for (int successor : graph.outgoingEdges(node)) {
if (!filter.match(successor) || visitIndex[successor] > 0) {
continue;
}
stack.push(successor);
}
for (int i = 0; i < headerIndex.length; ++i) {
if (visitIndex[i] > 0) {
headerIndex[i] = graph.size() + 1;
}
}
}
return components.toArray(new int[0][]);
}

View File

@ -81,22 +81,6 @@ public class IrreducibleGraphConverter {
}
}
private int[] reachUnder(DJGraph djGraph, int back, int header) {
IntSet naturalLoop = IntOpenHashSet.from(header);
IntegerStack stack = new IntegerStack(djGraph.getGraph().size());
stack.push(back);
while (!stack.isEmpty()) {
int node = stack.pop();
if (!naturalLoop.add(node)) {
continue;
}
for (int pred : djGraph.getGraph().incomingEdges(node)) {
stack.push(pred);
}
}
return naturalLoop.toArray();
}
private void handleStronglyConnectedComponent(DJGraph djGraph, int[] scc, int[][] nodeMap) {
// Find shared dominator
int sharedDom = scc[0];
@ -104,6 +88,13 @@ public class IrreducibleGraphConverter {
sharedDom = djGraph.getDomTree().commonDominatorOf(sharedDom, scc[i]);
}
for (int i = 0; i < scc.length; ++i) {
if (scc[i] == sharedDom) {
djGraph.collapse(scc);
return;
}
}
// Partition SCC into domains
DisjointSet partitions = new DisjointSet();
int[] sccBack = new int[djGraph.getGraph().size()];
@ -154,7 +145,9 @@ public class IrreducibleGraphConverter {
splitStronglyConnectedComponent(djGraph, domainNodes, sharedDom, scc, nodeMap);
// Collapse
djGraph.collapse(scc);
int[] sccAndTop = Arrays.copyOf(scc, scc.length + 1);
sccAndTop[scc.length] = sharedDom;
djGraph.collapse(sccAndTop);
}
private void splitStronglyConnectedComponent(DJGraph djGraph, IntSet domain, int sharedDom,