coloring now requires numbered graphs. a performance hack.

This commit is contained in:
Julian Dolby 2013-11-21 14:27:27 -05:00
parent 8888d77f97
commit dedbc2d443
2 changed files with 58 additions and 27 deletions

View File

@ -17,32 +17,51 @@ import junit.framework.Assert;
import org.junit.Test;
import com.ibm.wala.util.collections.HashMapFactory;
import com.ibm.wala.util.collections.Pair;
import com.ibm.wala.util.graph.Graph;
import com.ibm.wala.util.graph.impl.SlowSparseNumberedGraph;
import com.ibm.wala.util.graph.NumberedGraph;
import com.ibm.wala.util.graph.impl.DelegatingNumberedGraph;
import com.ibm.wala.util.graph.impl.NodeWithNumberedEdges;
import com.ibm.wala.util.graph.traverse.WelshPowell;
public class WelshPowellTest {
private <T> void assertColoring(Graph<T> G, Map<T,Integer> colors) {
for(T n : G) {
for(Iterator<T> ss = G.getSuccNodes(n); ss.hasNext(); ) {
private class TypedNode<T> extends NodeWithNumberedEdges {
private final T data;
private TypedNode(T data) {
this.data = data;
}
@Override
public String toString() {
return data.toString();
}
}
private <T> void assertColoring(NumberedGraph<TypedNode<T>> G, Map<TypedNode<T>,Integer> colors) {
for(TypedNode<T> n : G) {
for(Iterator<TypedNode<T>> ss = G.getSuccNodes(n); ss.hasNext(); ) {
Assert.assertTrue(colors.get(n).intValue() != colors.get(ss.next()).intValue());
}
for(Iterator<T> ps = G.getPredNodes(n); ps.hasNext(); ) {
for(Iterator<TypedNode<T>> ps = G.getPredNodes(n); ps.hasNext(); ) {
Assert.assertTrue(colors.get(n).intValue() != colors.get(ps.next()).intValue());
}
}
}
private <T> Graph<T> buildGraph(T[][] data) {
SlowSparseNumberedGraph<T> G = SlowSparseNumberedGraph.make();
private <T> NumberedGraph<TypedNode<T>> buildGraph(T[][] data) {
DelegatingNumberedGraph<TypedNode<T>> G = new DelegatingNumberedGraph<TypedNode<T>>();
Map<T,TypedNode<T>> nodes = HashMapFactory.make();
for(int i = 0; i < data.length; i++) {
G.addNode(data[i][0]);
TypedNode<T> n = new TypedNode<T>(data[i][0]);
nodes.put(data[i][0], n);
G.addNode(n);
}
for(int i = 0; i < data.length; i++) {
for(int j = 1; j < data[i].length; j++) {
G.addEdge(data[i][0], data[i][j]);
G.addEdge(nodes.get(data[i][0]), nodes.get(data[i][j]));
}
}
@ -51,7 +70,7 @@ public class WelshPowellTest {
@Test
public void testOne() {
Graph<Integer> G =
NumberedGraph<TypedNode<Integer>> G =
buildGraph(new Integer[][]{
new Integer[]{1, 6, 7, 8},
new Integer[]{2, 5, 7, 8},
@ -61,7 +80,7 @@ public class WelshPowellTest {
new Integer[]{6, 3, 1, 4},
new Integer[]{7, 1, 2, 4},
new Integer[]{8, 1, 2, 3}});
Pair<Map<Integer, Integer>,Integer> colors = new WelshPowell<Integer>().color(G);
Pair<Map<TypedNode<Integer>, Integer>,Integer> colors = new WelshPowell<TypedNode<Integer>>().color(G);
System.err.println(colors);
assertColoring(G, colors.fst);
Assert.assertTrue(colors.snd.intValue() <= 4);
@ -69,7 +88,7 @@ public class WelshPowellTest {
@Test
public void testTwo() {
Graph<String> G =
NumberedGraph<TypedNode<String>> G =
buildGraph(new String[][] {
new String[]{"poly1", "poly2", "star1", "poly5"},
new String[]{"poly2", "poly1", "star2", "poly3"},
@ -81,7 +100,7 @@ public class WelshPowellTest {
new String[]{"star3", "poly3", "star1", "star5"},
new String[]{"star4", "poly4", "star1", "star2"},
new String[]{"star5", "poly5", "star2", "star3"}});
Pair<Map<String, Integer>,Integer> colors = new WelshPowell<String>().color(G);
Pair<Map<TypedNode<String>, Integer>,Integer> colors = new WelshPowell<TypedNode<String>>().color(G);
System.err.println(colors);
assertColoring(G, colors.fst);
Assert.assertTrue(colors.snd.intValue() == 3);

View File

@ -18,11 +18,12 @@ import java.util.TreeSet;
import com.ibm.wala.util.collections.HashMapFactory;
import com.ibm.wala.util.collections.Pair;
import com.ibm.wala.util.graph.Graph;
import com.ibm.wala.util.graph.INodeWithNumber;
import com.ibm.wala.util.graph.NumberedGraph;
public class WelshPowell<T> {
public class WelshPowell<T extends INodeWithNumber> {
public static <T> Comparator<T> defaultComparator(final Graph<T> G) {
public static <T> Comparator<T> defaultComparator(final NumberedGraph<T> G) {
return new Comparator<T>() {
@Override
@ -38,12 +39,15 @@ public class WelshPowell<T> {
};
}
public Pair<Map<T,Integer>, Integer> color(final Graph<T> G) {
public Pair<Map<T,Integer>, Integer> color(final NumberedGraph<T> G) {
return color(G, defaultComparator(G));
}
public Pair<Map<T,Integer>, Integer> color(final Graph<T> G, Comparator<T> order) {
Map<T, Integer> colors = HashMapFactory.make();
public Pair<Map<T,Integer>, Integer> color(final NumberedGraph<T> G, Comparator<T> order) {
int[] colors = new int[ G.getNumberOfNodes() ];
for(int i = 0; i < colors.length; i++) {
colors[i] = -1;
}
SortedSet<T> vertices = new TreeSet<T>(order);
@ -52,30 +56,34 @@ public class WelshPowell<T> {
}
int currentColor = 0;
int colored = 0;
while(colors.size() < G.getNumberOfNodes()) {
while(colored < G.getNumberOfNodes()) {
for(T n : vertices) {
if (! colors.containsKey(n)) {
colors.put(n, currentColor);
int id = n.getGraphNodeId();
if (colors[id] == -1) {
colors[id] = currentColor;
colored++;
for(T m : vertices) {
if (! colors.containsKey(m)) {
if (colors[m.getGraphNodeId()] == -1) {
color_me: {
for(Iterator<T> ps = G.getPredNodes(m); ps.hasNext(); ) {
T p = ps.next();
if (colors.containsKey(p) && colors.get(p) == currentColor) {
if (colors[ p.getGraphNodeId() ] == currentColor) {
break color_me;
}
}
for(Iterator<T> ss = G.getSuccNodes(m); ss.hasNext(); ) {
T s = ss.next();
if (colors.containsKey(s) && colors.get(s) == currentColor) {
if (colors[s.getGraphNodeId()] == currentColor) {
break color_me;
}
}
colors.put(m, currentColor);
colors[m.getGraphNodeId()] = currentColor;
colored++;
}
}
}
@ -85,7 +93,11 @@ public class WelshPowell<T> {
}
}
return Pair.make(colors, currentColor);
Map<T,Integer> colorMap = HashMapFactory.make();
for(int i = 0; i < colors.length; i++) {
colorMap.put(G.getNode(i), colors[i]);
}
return Pair.make(colorMap, currentColor);
}
}