mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -08:00
Add more complicated irreducible graph test
This commit is contained in:
parent
33b319ce16
commit
0fe826ade8
|
@ -69,11 +69,13 @@ public class DJGraph {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add dom edges
|
// Add dom edges
|
||||||
for (int i = 1; i < graph.size(); ++i) {
|
for (int i = 0; i < graph.size(); ++i) {
|
||||||
int j = domTree.immediateDominatorOf(i);
|
int j = domTree.immediateDominatorOf(i);
|
||||||
|
if (j >= 0) {
|
||||||
graph.addEdge(j, i);
|
graph.addEdge(j, i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void buildLevels() {
|
private void buildLevels() {
|
||||||
List<IntegerArray> builder = new ArrayList<>();
|
List<IntegerArray> builder = new ArrayList<>();
|
||||||
|
|
|
@ -91,14 +91,13 @@ public final class GraphUtils {
|
||||||
|
|
||||||
for (int startNode : start) {
|
for (int startNode : start) {
|
||||||
stack.push(startNode);
|
stack.push(startNode);
|
||||||
IntegerArray currentComponent = new IntegerArray(1);
|
IntegerStack currentComponent = new IntegerStack(1);
|
||||||
while (!stack.isEmpty()) {
|
while (!stack.isEmpty()) {
|
||||||
int node = stack.pop();
|
int node = stack.pop();
|
||||||
if (visitIndex[node] > 0) {
|
if (visitIndex[node] > 0) {
|
||||||
if (headerIndex[node] > 0) {
|
if (headerIndex[node] > 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
currentComponent.add(node);
|
|
||||||
int hdr = visitIndex[node];
|
int hdr = visitIndex[node];
|
||||||
for (int successor : graph.outgoingEdges(node)) {
|
for (int successor : graph.outgoingEdges(node)) {
|
||||||
if (!filter.match(successor)) {
|
if (!filter.match(successor)) {
|
||||||
|
@ -111,15 +110,21 @@ public final class GraphUtils {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (hdr == visitIndex[node]) {
|
if (hdr == visitIndex[node]) {
|
||||||
components.add(currentComponent.getAll());
|
IntegerArray componentMembers = new IntegerArray(graph.size());
|
||||||
for (int componentMember : currentComponent.getAll()) {
|
while (true) {
|
||||||
|
int componentMember = currentComponent.pop();
|
||||||
|
componentMembers.add(componentMember);
|
||||||
headerIndex[componentMember] = graph.size() + 1;
|
headerIndex[componentMember] = graph.size() + 1;
|
||||||
|
if (visitIndex[componentMember] == hdr) {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
currentComponent.clear();
|
}
|
||||||
|
components.add(componentMembers.getAll());
|
||||||
}
|
}
|
||||||
headerIndex[node] = hdr;
|
headerIndex[node] = hdr;
|
||||||
} else {
|
} else {
|
||||||
visitIndex[node] = ++lastIndex;
|
visitIndex[node] = ++lastIndex;
|
||||||
|
currentComponent.push(node);
|
||||||
stack.push(node);
|
stack.push(node);
|
||||||
for (int successor : graph.outgoingEdges(node)) {
|
for (int successor : graph.outgoingEdges(node)) {
|
||||||
if (!filter.match(successor) || visitIndex[successor] > 0) {
|
if (!filter.match(successor) || visitIndex[successor] > 0) {
|
||||||
|
|
|
@ -63,17 +63,6 @@ class IrreducibleGraphConverter {
|
||||||
for (int[] scc : sccs) {
|
for (int[] scc : sccs) {
|
||||||
if (scc.length > 1) {
|
if (scc.length > 1) {
|
||||||
handleStronglyConnectedComponent(djGraph, scc, nodeMap);
|
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) {
|
for (int i = 0; i < scc.length; ++i) {
|
||||||
if (scc[i] == sharedDom) {
|
if (scc[i] == sharedDom) {
|
||||||
djGraph.collapse(scc);
|
collapse(djGraph, scc, nodeMap);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -146,7 +135,7 @@ class IrreducibleGraphConverter {
|
||||||
// Collapse
|
// Collapse
|
||||||
int[] sccAndTop = Arrays.copyOf(scc, scc.length + 1);
|
int[] sccAndTop = Arrays.copyOf(scc, scc.length + 1);
|
||||||
sccAndTop[scc.length] = sharedDom;
|
sccAndTop[scc.length] = sharedDom;
|
||||||
djGraph.collapse(sccAndTop);
|
collapse(djGraph, sccAndTop, nodeMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void splitStronglyConnectedComponent(DJGraph djGraph, IntSet domain, int sharedDom,
|
private void splitStronglyConnectedComponent(DJGraph djGraph, IntSet domain, int sharedDom,
|
||||||
|
@ -241,6 +230,20 @@ class IrreducibleGraphConverter {
|
||||||
handleLoops(new DJGraph(builder.build(), mappedWeight), newNodeMap);
|
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) {
|
private static int[] flatten(int[][] array) {
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (int i = 0; i < array.length; ++i) {
|
for (int i = 0; i < array.length; ++i) {
|
||||||
|
|
|
@ -107,6 +107,41 @@ public class GraphTest {
|
||||||
assertThat(sccs[2], is(new int[] { 2 }));
|
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
|
@Test
|
||||||
public void irreducibleGraphSplit() {
|
public void irreducibleGraphSplit() {
|
||||||
GraphBuilder builder = new GraphBuilder();
|
GraphBuilder builder = new GraphBuilder();
|
||||||
|
@ -152,6 +187,39 @@ public class GraphTest {
|
||||||
assertTrue("Should be equialent", isEquialent(backend, graph));
|
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) {
|
private boolean isEquialent(DefaultGraphSplittingBackend backend, Graph proto) {
|
||||||
Graph graph = backend.getGraph();
|
Graph graph = backend.getGraph();
|
||||||
for (int node = 0; node < graph.size(); ++node) {
|
for (int node = 0; node < graph.size(); ++node) {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user