mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -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.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Alexey Andreev
|
* @author Alexey Andreev
|
||||||
|
@ -111,9 +110,7 @@ public final class GraphUtils {
|
||||||
*/
|
*/
|
||||||
public static int[][] findStronglyConnectedComponents(Graph graph, int[] start, GraphNodeFilter filter) {
|
public static int[][] findStronglyConnectedComponents(Graph graph, int[] start, GraphNodeFilter filter) {
|
||||||
List<int[]> components = new ArrayList<>();
|
List<int[]> components = new ArrayList<>();
|
||||||
boolean[] done = new boolean[graph.size()];
|
|
||||||
int[] visitIndex = new int[graph.size()];
|
int[] visitIndex = new int[graph.size()];
|
||||||
Arrays.fill(visitIndex, -1);
|
|
||||||
int[] headerIndex = new int[graph.size()];
|
int[] headerIndex = new int[graph.size()];
|
||||||
int lastIndex = 0;
|
int lastIndex = 0;
|
||||||
IntegerStack stack = new IntegerStack(graph.size());
|
IntegerStack stack = new IntegerStack(graph.size());
|
||||||
|
@ -124,36 +121,32 @@ public final class GraphUtils {
|
||||||
IntegerArray currentComponent = new IntegerArray(1);
|
IntegerArray currentComponent = new IntegerArray(1);
|
||||||
while (!stack.isEmpty()) {
|
while (!stack.isEmpty()) {
|
||||||
int node = stack.pop();
|
int node = stack.pop();
|
||||||
if (visitIndex[node] == 0) {
|
if (visitIndex[node] > 0) {
|
||||||
if (done[node]) {
|
|
||||||
currentComponent.add(node);
|
currentComponent.add(node);
|
||||||
int hdr = 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)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!done[successor]) {
|
if (headerIndex[successor] == 0) {
|
||||||
hdr = Math.min(hdr, visitIndex[successor]);
|
hdr = Math.min(hdr, visitIndex[successor]);
|
||||||
} else {
|
} else {
|
||||||
hdr = Math.min(hdr, headerIndex[successor]);
|
hdr = Math.min(hdr, headerIndex[successor]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (hdr == node) {
|
if (hdr == visitIndex[node]) {
|
||||||
components.add(currentComponent.getAll());
|
components.add(currentComponent.getAll());
|
||||||
currentComponent.clear();
|
currentComponent.clear();
|
||||||
}
|
}
|
||||||
headerIndex[node] = hdr;
|
headerIndex[node] = hdr;
|
||||||
} else {
|
|
||||||
done[node] = true;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
visitIndex[node] = ++lastIndex;
|
visitIndex[node] = ++lastIndex;
|
||||||
stack.push(node);
|
stack.push(node);
|
||||||
for (int successor : graph.outgoingEdges(node)) {
|
for (int successor : graph.outgoingEdges(node)) {
|
||||||
if (!filter.match(successor)) {
|
if (!filter.match(successor) || visitIndex[successor] > 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
stack.push(node);
|
stack.push(successor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -243,7 +236,6 @@ public final class GraphUtils {
|
||||||
return domFrontiers;
|
return domFrontiers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static int[] makeSet(IntegerArray array) {
|
private static int[] makeSet(IntegerArray array) {
|
||||||
int[] items = array.getAll();
|
int[] items = array.getAll();
|
||||||
int[] set = new int[items.length];
|
int[] set = new int[items.length];
|
||||||
|
|
|
@ -55,7 +55,7 @@ public class IrreducibleGraphConverter {
|
||||||
irreducible = true;
|
irreducible = true;
|
||||||
}
|
}
|
||||||
} else if (djGraph.isBackJoin(node, pred)) {
|
} 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) {
|
private int[] reachUnder(DJGraph djGraph, int back, int header) {
|
||||||
// TODO: implement
|
IntSet naturalLoop = IntOpenHashSet.from(header);
|
||||||
return null;
|
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) {
|
private void handleStronglyConnectedComponent(DJGraph djGraph, int[] scc, int[] nodeMap) {
|
||||||
|
@ -126,6 +137,9 @@ public class IrreducibleGraphConverter {
|
||||||
|
|
||||||
// Split
|
// Split
|
||||||
splitStronglyConnectedComponent(domainNodes, sharedDom, scc, nodeMap);
|
splitStronglyConnectedComponent(domainNodes, sharedDom, scc, nodeMap);
|
||||||
|
|
||||||
|
// Collapse
|
||||||
|
djGraph.collapse(scc);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void splitStronglyConnectedComponent(IntSet domain, int sharedDom, int[] scc, int[] nodeMap) {
|
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