mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
Complete node splitting algorithm. Add test case for SCC finder.
This commit is contained in:
parent
77b42e677a
commit
f106afb034
|
@ -19,7 +19,6 @@ import java.util.ArrayList;
|
|||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
|
@ -111,9 +110,7 @@ public final class GraphUtils {
|
|||
*/
|
||||
public static int[][] findStronglyConnectedComponents(Graph graph, int[] start, GraphNodeFilter filter) {
|
||||
List<int[]> components = new ArrayList<>();
|
||||
boolean[] done = new boolean[graph.size()];
|
||||
int[] visitIndex = new int[graph.size()];
|
||||
Arrays.fill(visitIndex, -1);
|
||||
int[] headerIndex = new int[graph.size()];
|
||||
int lastIndex = 0;
|
||||
IntegerStack stack = new IntegerStack(graph.size());
|
||||
|
@ -124,36 +121,32 @@ public final class GraphUtils {
|
|||
IntegerArray currentComponent = new IntegerArray(1);
|
||||
while (!stack.isEmpty()) {
|
||||
int node = stack.pop();
|
||||
if (visitIndex[node] == 0) {
|
||||
if (done[node]) {
|
||||
currentComponent.add(node);
|
||||
int hdr = node;
|
||||
for (int successor : graph.outgoingEdges(node)) {
|
||||
if (!filter.match(successor)) {
|
||||
continue;
|
||||
}
|
||||
if (!done[successor]) {
|
||||
hdr = Math.min(hdr, visitIndex[successor]);
|
||||
} else {
|
||||
hdr = Math.min(hdr, headerIndex[successor]);
|
||||
}
|
||||
}
|
||||
if (hdr == node) {
|
||||
components.add(currentComponent.getAll());
|
||||
currentComponent.clear();
|
||||
}
|
||||
headerIndex[node] = hdr;
|
||||
} else {
|
||||
done[node] = true;
|
||||
}
|
||||
} else {
|
||||
visitIndex[node] = ++lastIndex;
|
||||
stack.push(node);
|
||||
if (visitIndex[node] > 0) {
|
||||
currentComponent.add(node);
|
||||
int hdr = visitIndex[node];
|
||||
for (int successor : graph.outgoingEdges(node)) {
|
||||
if (!filter.match(successor)) {
|
||||
continue;
|
||||
}
|
||||
stack.push(node);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -243,7 +236,6 @@ public final class GraphUtils {
|
|||
return domFrontiers;
|
||||
}
|
||||
|
||||
|
||||
private static int[] makeSet(IntegerArray array) {
|
||||
int[] items = array.getAll();
|
||||
int[] set = new int[items.length];
|
||||
|
|
|
@ -55,7 +55,7 @@ public class IrreducibleGraphConverter {
|
|||
irreducible = true;
|
||||
}
|
||||
} else if (djGraph.isBackJoin(node, pred)) {
|
||||
djGraph.collapse(reachUnder(djGraph, pred));
|
||||
djGraph.collapse(reachUnder(djGraph, pred, node));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -68,9 +68,20 @@ public class IrreducibleGraphConverter {
|
|||
}
|
||||
}
|
||||
|
||||
private int[] reachUnder(DJGraph djGraph, int top) {
|
||||
// TODO: implement
|
||||
return null;
|
||||
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) {
|
||||
|
@ -126,6 +137,9 @@ public class IrreducibleGraphConverter {
|
|||
|
||||
// Split
|
||||
splitStronglyConnectedComponent(domainNodes, sharedDom, scc, nodeMap);
|
||||
|
||||
// Collapse
|
||||
djGraph.collapse(scc);
|
||||
}
|
||||
|
||||
private void splitStronglyConnectedComponent(IntSet domain, int sharedDom, int[] scc, int[] nodeMap) {
|
||||
|
|
73
teavm-core/src/test/java/org/teavm/common/GraphTest.java
Normal file
73
teavm-core/src/test/java/org/teavm/common/GraphTest.java
Normal file
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* Copyright 2015 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.common;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public class GraphTest {
|
||||
@Test
|
||||
public void stronglyConnectedComponentsCalculated() {
|
||||
GraphBuilder builder = new GraphBuilder();
|
||||
builder.addEdge(0, 1);
|
||||
builder.addEdge(1, 2);
|
||||
builder.addEdge(2, 3);
|
||||
builder.addEdge(2, 4);
|
||||
builder.addEdge(3, 5);
|
||||
builder.addEdge(4, 5);
|
||||
builder.addEdge(5, 6);
|
||||
builder.addEdge(6, 1);
|
||||
builder.addEdge(6, 7);
|
||||
builder.addEdge(7, 8);
|
||||
builder.addEdge(7, 9);
|
||||
builder.addEdge(8, 1);
|
||||
builder.addEdge(9, 10);
|
||||
builder.addEdge(10, 11);
|
||||
builder.addEdge(11, 12);
|
||||
builder.addEdge(12, 11);
|
||||
builder.addEdge(12, 13);
|
||||
Graph graph = builder.build();
|
||||
|
||||
int[][] sccs = GraphUtils.findStronglyConnectedComponents(graph, new int[] { 0 }, new GraphNodeFilter() {
|
||||
@Override public boolean match(int node) {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
for (int i = 0; i < sccs.length; ++i) {
|
||||
Arrays.sort(sccs[i]);
|
||||
}
|
||||
Arrays.sort(sccs, new Comparator<int[]>() {
|
||||
@Override public int compare(int[] o1, int[] o2) {
|
||||
return Integer.compare(o1[0], o2[0]);
|
||||
}
|
||||
});
|
||||
|
||||
assertThat(sccs[0], is(new int[] { 0 }));
|
||||
assertThat(sccs[1], is(new int[] { 1, 2, 3, 4, 5, 6, 7, 8 }));
|
||||
assertThat(sccs[2], is(new int[] { 9 }));
|
||||
assertThat(sccs[3], is(new int[] { 10 }));
|
||||
assertThat(sccs[4], is(new int[] { 11, 12 }));
|
||||
assertThat(sccs[5], is(new int[] { 13 }));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user