/******************************************************************************* * Copyright (c) 2013 IBM Corporation. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package com.ibm.wala.util.graph.traverse; import java.util.Comparator; import java.util.Iterator; import java.util.Map; import java.util.SortedSet; import java.util.TreeSet; import com.ibm.wala.util.collections.HashMapFactory; import com.ibm.wala.util.graph.INodeWithNumber; import com.ibm.wala.util.graph.NumberedGraph; public class WelshPowell<T extends INodeWithNumber> { public static class ColoredVertices<T> { private final boolean fullColoring; private final Map<T, Integer> colors; private final int numColors; public boolean isFullColoring() { return fullColoring; } public Map<T, Integer> getColors() { return colors; } public int getNumColors() { return numColors; } public ColoredVertices(boolean fullColoring, NumberedGraph<T> G, int colors[], int numColors) { this(fullColoring, makeMap(G, colors), numColors); } private static <T> Map<T, Integer> makeMap(NumberedGraph<T> G, int[] colors) { Map<T,Integer> colorMap = HashMapFactory.make(); for(int i = 0; i < colors.length; i++) { if (colors[i] != -1) { colorMap.put(G.getNode(i), colors[i]); } } return colorMap; } public ColoredVertices(boolean fullColoring, Map<T, Integer> colors, int numColors) { this.fullColoring = fullColoring; this.colors = colors; this.numColors = numColors; } } public static <T> Comparator<T> defaultComparator(final NumberedGraph<T> G) { return new Comparator<T>() { @Override public int compare(T o1, T o2) { int o1edges = G.getSuccNodeCount(o1) + G.getPredNodeCount(o1); int o2edges = G.getSuccNodeCount(o2) + G.getPredNodeCount(o2); if (o1edges != o2edges) { return o2edges - o1edges; } else { return o2.toString().compareTo(o1.toString()); } } }; } public ColoredVertices<T> color(final NumberedGraph<T> G) { return color(G, defaultComparator(G), Integer.MAX_VALUE); } public ColoredVertices<T> color(final NumberedGraph<T> G, int maxColors) { return color(G, defaultComparator(G), maxColors); } public ColoredVertices<T> color(final NumberedGraph<T> G, Comparator<T> order, int maxColors) { int[] colors = new int[ G.getMaxNumber() + 1]; for(int i = 0; i < colors.length; i++) { colors[i] = -1; } SortedSet<T> vertices = new TreeSet<T>(order); for (T n : G) { vertices.add(n); } int currentColor = 0; int colored = 0; for(T n : vertices) { int id = n.getGraphNodeId(); if (colors[id] == -1) { colors[id] = currentColor; colored++; for(T m : vertices) { if (colors[m.getGraphNodeId()] == -1) { color_me: { for(Iterator<T> ps = G.getPredNodes(m); ps.hasNext(); ) { T p = ps.next(); if (colors[ p.getGraphNodeId() ] == currentColor) { break color_me; } } for(Iterator<T> ss = G.getSuccNodes(m); ss.hasNext(); ) { T s = ss.next(); if (colors[s.getGraphNodeId()] == currentColor) { break color_me; } } colors[m.getGraphNodeId()] = currentColor; colored++; if (currentColor == maxColors - 1) { return new ColoredVertices<T>(false, G, colors, currentColor); } } } } currentColor++; if (currentColor == maxColors - 1) { return new ColoredVertices<T>(false, G, colors, currentColor); } } } assert colored == G.getNumberOfNodes(); return new ColoredVertices<T>(true, G, colors, currentColor); } }