Add more complicated irreducible graph test

This commit is contained in:
konsoletyper 2015-03-05 23:35:12 +03:00
parent 33b319ce16
commit 0fe826ade8
4 changed files with 98 additions and 20 deletions

View File

@ -69,11 +69,13 @@ public class DJGraph {
}
// Add dom edges
for (int i = 1; i < graph.size(); ++i) {
for (int i = 0; i < graph.size(); ++i) {
int j = domTree.immediateDominatorOf(i);
if (j >= 0) {
graph.addEdge(j, i);
}
}
}
private void buildLevels() {
List<IntegerArray> builder = new ArrayList<>();

View File

@ -91,14 +91,13 @@ public final class GraphUtils {
for (int startNode : start) {
stack.push(startNode);
IntegerArray currentComponent = new IntegerArray(1);
IntegerStack currentComponent = new IntegerStack(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)) {
@ -111,15 +110,21 @@ public final class GraphUtils {
}
}
if (hdr == visitIndex[node]) {
components.add(currentComponent.getAll());
for (int componentMember : currentComponent.getAll()) {
IntegerArray componentMembers = new IntegerArray(graph.size());
while (true) {
int componentMember = currentComponent.pop();
componentMembers.add(componentMember);
headerIndex[componentMember] = graph.size() + 1;
if (visitIndex[componentMember] == hdr) {
break;
}
currentComponent.clear();
}
components.add(componentMembers.getAll());
}
headerIndex[node] = hdr;
} else {
visitIndex[node] = ++lastIndex;
currentComponent.push(node);
stack.push(node);
for (int successor : graph.outgoingEdges(node)) {
if (!filter.match(successor) || visitIndex[successor] > 0) {

View File

@ -63,17 +63,6 @@ class IrreducibleGraphConverter {
for (int[] scc : sccs) {
if (scc.length > 1) {
handleStronglyConnectedComponent(djGraph, scc, nodeMap);
int cls = djGraph.collapse(scc);
IntegerArray nodes = new IntegerArray(djGraph.getGraph().size());
for (int representative : djGraph.classRepresentatives(cls)) {
for (int node : nodeMap[representative]) {
nodes.add(node);
}
}
for (int representative : djGraph.classRepresentatives(cls)) {
nodeMap[representative] = new int[0];
}
nodeMap[cls] = nodes.getAll();
}
}
}
@ -89,7 +78,7 @@ class IrreducibleGraphConverter {
for (int i = 0; i < scc.length; ++i) {
if (scc[i] == sharedDom) {
djGraph.collapse(scc);
collapse(djGraph, scc, nodeMap);
return;
}
}
@ -146,7 +135,7 @@ class IrreducibleGraphConverter {
// Collapse
int[] sccAndTop = Arrays.copyOf(scc, scc.length + 1);
sccAndTop[scc.length] = sharedDom;
djGraph.collapse(sccAndTop);
collapse(djGraph, sccAndTop, nodeMap);
}
private void splitStronglyConnectedComponent(DJGraph djGraph, IntSet domain, int sharedDom,
@ -241,6 +230,20 @@ class IrreducibleGraphConverter {
handleLoops(new DJGraph(builder.build(), mappedWeight), newNodeMap);
}
private void collapse(DJGraph djGraph, int[] scc, int[][] nodeMap) {
int cls = djGraph.collapse(scc);
IntegerArray nodes = new IntegerArray(djGraph.getGraph().size());
for (int representative : djGraph.classRepresentatives(cls)) {
for (int node : nodeMap[representative]) {
nodes.add(node);
}
}
for (int representative : djGraph.classRepresentatives(cls)) {
nodeMap[representative] = new int[0];
}
nodeMap[cls] = nodes.getAll();
}
private static int[] flatten(int[][] array) {
int count = 0;
for (int i = 0; i < array.length; ++i) {

View File

@ -107,6 +107,41 @@ public class GraphTest {
assertThat(sccs[2], is(new int[] { 2 }));
}
@Test
public void stronglyConnectedComponentCalculated4() {
GraphBuilder builder = new GraphBuilder();
builder.addEdge(0, 1);
builder.addEdge(0, 2);
builder.addEdge(1, 2);
builder.addEdge(1, 3);
builder.addEdge(1, 4);
builder.addEdge(2, 1);
builder.addEdge(2, 3);
builder.addEdge(3, 4);
builder.addEdge(4, 5);
builder.addEdge(4, 6);
builder.addEdge(5, 6);
builder.addEdge(6, 5);
builder.addEdge(6, 7);
builder.addEdge(7, 4);
builder.addEdge(7, 3);
builder.addEdge(7, 8);
builder.addEdge(8, 7);
Graph graph = builder.build();
int[][] sccs = GraphUtils.findStronglyConnectedComponents(graph, new int[] { 1, 2, 3, 4 },
new GraphNodeFilter() {
@Override public boolean match(int node) {
return node != 0;
}
});
sortSccs(sccs);
assertThat(sccs.length, is(2));
assertThat(sccs[0], is(new int[] { 1, 2 }));
assertThat(sccs[1], is(new int[] { 3, 4, 5, 6, 7, 8 }));
}
@Test
public void irreducibleGraphSplit() {
GraphBuilder builder = new GraphBuilder();
@ -152,6 +187,39 @@ public class GraphTest {
assertTrue("Should be equialent", isEquialent(backend, graph));
}
@Test
public void irreducibleGraphSplit3() {
GraphBuilder builder = new GraphBuilder();
builder.addEdge(0, 1);
builder.addEdge(0, 2);
builder.addEdge(1, 2);
builder.addEdge(1, 3);
builder.addEdge(1, 4);
builder.addEdge(2, 1);
builder.addEdge(2, 3);
builder.addEdge(3, 4);
builder.addEdge(4, 5);
builder.addEdge(4, 6);
builder.addEdge(5, 6);
builder.addEdge(6, 5);
builder.addEdge(6, 7);
builder.addEdge(7, 4);
builder.addEdge(7, 3);
builder.addEdge(7, 8);
builder.addEdge(8, 7);
Graph graph = builder.build();
DefaultGraphSplittingBackend backend = new DefaultGraphSplittingBackend(graph);
int[] weights = new int[graph.size()];
Arrays.fill(weights, 1);
GraphUtils.splitIrreducibleGraph(graph, weights, backend);
Graph result = backend.getGraph();
assertTrue("Should be irreducible", GraphUtils.isIrreducible(graph));
assertFalse("Should be reducible", GraphUtils.isIrreducible(result));
assertTrue("Should be equialent", isEquialent(backend, graph));
}
private boolean isEquialent(DefaultGraphSplittingBackend backend, Graph proto) {
Graph graph = backend.getGraph();
for (int node = 0; node < graph.size(); ++node) {