Skip to content

Commit

Permalink
Fix WelshPowell algorithm
Browse files Browse the repository at this point in the history
  • Loading branch information
gsavin committed May 27, 2013
1 parent 46be959 commit a07ee7a
Show file tree
Hide file tree
Showing 2 changed files with 156 additions and 137 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/*
* Copyright 2006 - 2012
* Stefan Balev <[email protected]>
* Julien Baudry <[email protected]>
* Antoine Dutot <[email protected]>
* Yoann Pigné <[email protected]>
* Guilhelm Savin <[email protected]>
*
* This file is part of GraphStream <http://graphstream-project.org>.
*
* GraphStream is a library whose purpose is to handle static or dynamic
* graph, create them from scratch, file or any source and display them.
*
* This program is free software distributed under the terms of two licenses, the
* CeCILL-C license that fits European law, and the GNU Lesser General Public
* License. You can use, modify and/ or redistribute the software under the terms
* of the CeCILL-C license as circulated by CEA, CNRS and INRIA at the following
* URL <http://www.cecill.info> or under the terms of the GNU LGPL as published by
* the Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* The fact that you are presently reading this means that you have had
* knowledge of the CeCILL-C and LGPL licenses and that you accept their terms.
*/
package org.graphstream.algorithm.coloring.test;

import java.io.IOException;
import java.io.StringReader;

import org.graphstream.algorithm.coloring.WelshPowell;
import org.graphstream.graph.ElementNotFoundException;
import org.graphstream.graph.Graph;
import org.graphstream.graph.Node;
import org.graphstream.graph.implementations.DefaultGraph;
import org.graphstream.stream.GraphParseException;
import org.graphstream.stream.file.FileSourceDGS;

public class WelshPowellDemo {
// B-(1)-C
// / \
// (1) (10)
// / \
// A F
// \ /
// (1) (1)
// \ /
// D-(1)-E
static String my_graph = "DGS004\n" + "my 0 0\n" + "an A \n" + "an B \n"
+ "an C \n" + "an D \n" + "an E \n" + "an F \n"
+ "ae AB A B weight:1 \n" + "ae AD A D weight:1 \n"
+ "ae BC B C weight:1 \n" + "ae CF C F weight:10 \n"
+ "ae DE D E weight:1 \n" + "ae EF E F weight:1 \n";

public static void main(String[] args) throws IOException,
ElementNotFoundException, GraphParseException {
Graph graph = new DefaultGraph("Welsh Powell Test");
StringReader reader = new StringReader(my_graph);

FileSourceDGS source = new FileSourceDGS();
source.addSink(graph);
source.readAll(reader);

WelshPowell wp = new WelshPowell("color");
wp.init(graph);
wp.compute();

System.out.println("The chromatic number of this graph is : "
+ wp.getChromaticNumber());
for (Node n : graph) {
System.out.println("Node " + n.getId() + " : color "
+ n.getAttribute("color"));
}
}
}
212 changes: 75 additions & 137 deletions src/org/graphstream/algorithm/coloring/WelshPowell.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,10 @@
*/
package org.graphstream.algorithm.coloring;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.Iterator;
import java.util.PriorityQueue;
import java.util.LinkedList;

import org.graphstream.algorithm.Algorithm;
import org.graphstream.algorithm.util.FibonacciHeap;
import org.graphstream.graph.Graph;
import org.graphstream.graph.Node;

Expand Down Expand Up @@ -76,72 +74,44 @@
* <p>
* After computation (using {@link #compute()}, the algorithm result for the
* computation, the chromatic number, is accessible with the
* {@link #getChromaticNumber()} method. Colors (of "Integer" type) are stored in the graph as attributes (one for each node).
* By default the attribute name is "WelshPowell.color", but you can optional choose the
* attribute name.
* {@link #getChromaticNumber()} method. Colors (of "Integer" type) are stored
* in the graph as attributes (one for each node). By default the attribute name
* is "WelshPowell.color", but you can optional choose the attribute name.
* </p>
*
*
*
* <h2>Example</h2>
* import java.io.IOException;
* import java.io.StringReader;
* <h2>Example</h2> import java.io.IOException; import java.io.StringReader;
*
* import org.graphstream.algorithm.coloring.WelshPowell;
* import org.graphstream.graph.ElementNotFoundException;
* import org.graphstream.graph.Graph;
* import org.graphstream.graph.Node;
* import org.graphstream.graph.implementations.DefaultGraph;
* import org.graphstream.stream.GraphParseException;
* import org.graphstream.stream.file.FileSourceDGS;
* import org.graphstream.algorithm.coloring.WelshPowell; import
* org.graphstream.graph.ElementNotFoundException; import
* org.graphstream.graph.Graph; import org.graphstream.graph.Node; import
* org.graphstream.graph.implementations.DefaultGraph; import
* org.graphstream.stream.GraphParseException; import
* org.graphstream.stream.file.FileSourceDGS;
*
* public class WelshPowellTest {
* // B-(1)-C
* // / \
* // (1) (10)
* // / \
* // A F
* // \ /
* // (1) (1)
* // \ /
* // D-(1)-E
* static String my_graph =
* "DGS004\n"
* + "my 0 0\n"
* + "an A \n"
* + "an B \n"
* + "an C \n"
* + "an D \n"
* + "an E \n"
* + "an F \n"
* + "ae AB A B weight:1 \n"
* + "ae AD A D weight:1 \n"
* + "ae BC B C weight:1 \n"
* + "ae CF C F weight:10 \n"
* + "ae DE D E weight:1 \n"
* + "ae EF E F weight:1 \n"
* ;
* public static void main(String[] args) throws IOException, ElementNotFoundException, GraphParseException {
* Graph graph = new DefaultGraph("Welsh Powell Test");
* StringReader reader = new StringReader(my_graph);
*
* FileSourceDGS source = new FileSourceDGS();
* source.addSink(graph);
* source.readAll(reader);
*
* WelshPowell wp = new WelshPowell("color");
* wp.init(graph);
* wp.compute();
*
* System.out.println("The chromatic number of this graph is : "+wp.getChromaticNumber());
* for(Node n : graph){
* System.out.println("Node "+n.getId()+ " : color " +n.getAttribute("color"));
* }
* }
* }
* </pre>
* public class WelshPowellTest { // B-(1)-C // / \ // (1) (10) // / \ // A F //
* \ / // (1) (1) // \ / // D-(1)-E static String my_graph = "DGS004\n" +
* "my 0 0\n" + "an A \n" + "an B \n" + "an C \n" + "an D \n" + "an E \n" +
* "an F \n" + "ae AB A B weight:1 \n" + "ae AD A D weight:1 \n" +
* "ae BC B C weight:1 \n" + "ae CF C F weight:10 \n" + "ae DE D E weight:1 \n"
* + "ae EF E F weight:1 \n" ; public static void main(String[] args) throws
* IOException, ElementNotFoundException, GraphParseException { Graph graph =
* new DefaultGraph("Welsh Powell Test"); StringReader reader = new
* StringReader(my_graph);
*
* FileSourceDGS source = new FileSourceDGS(); source.addSink(graph);
* source.readAll(reader);
*
* WelshPowell wp = new WelshPowell("color"); wp.init(graph); wp.compute();
*
* System.out.println("The chromatic number of this graph is : "+wp.
* getChromaticNumber()); for(Node n : graph){
* System.out.println("Node "+n.getId()+ " : color " +n.getAttribute("color"));
* } } } </pre>
*
* This shall return:
*
* <pre>
* The chromatic number of this graph is : 3
* Node D : color 0
Expand All @@ -156,33 +126,33 @@
* <h2>Extra Feature</h2>
*
* <p>
* Consider you what to display the result of they coloring algorithm on a displayed graph,
* then adding the following code to the previous example may help you:
* Consider you what to display the result of they coloring algorithm on a
* displayed graph, then adding the following code to the previous example may
* help you:
* </p>
*
* <pre>
* Color[] cols = new Color[wp.getChromaticNumber()];
* for(int i=0;i< wp.getChromaticNumber();i++){
* cols[i]=Color.getHSBColor((float) (Math.random()), 0.8f, 0.9f);
* for (int i = 0; i &lt; wp.getChromaticNumber(); i++) {
* cols[i] = Color.getHSBColor((float) (Math.random()), 0.8f, 0.9f);
* }
* for(Node n : graph){
* int col = (int) n.getNumber("color");
* n.addAttribute("ui.style", "fill-color:rgba("+cols[col].getRed()+","+cols[col].getGreen()+","+cols[col].getBlue()+",200);" );
* for (Node n : graph) {
* int col = (int) n.getNumber(&quot;color&quot;);
* n.addAttribute(&quot;ui.style&quot;, &quot;fill-color:rgba(&quot; + cols[col].getRed() + &quot;,&quot;
* + cols[col].getGreen() + &quot;,&quot; + cols[col].getBlue() + &quot;,200);&quot;);
* }
*
* graph.display();
* </pre>
*
*
* @complexity
* This algorithm is known to use at most d(G)+1 colors where d(G) represents
* the largest value of the degree in the graph G.
*
* @reference
* Welsh, D. J. A.; Powell, M. B. (1967),
* "An upper bound for the chromatic number of a graph and its application to timetabling problems",
* The Computer Journal 10 (1): 85–86, doi:10.1093/comjnl/10.1.85
*
* @complexity This algorithm is known to use at most d(G)+1 colors where d(G)
* represents the largest value of the degree in the graph G.
*
* @reference Welsh, D. J. A.; Powell, M. B. (1967),
* "An upper bound for the chromatic number of a graph and its application to timetabling problems"
* , The Computer Journal 10 (1): 85–86, doi:10.1093/comjnl/10.1.85
*
* @version 0.1 30/08/2007
* @author Frédéric Guinand
Expand Down Expand Up @@ -220,8 +190,8 @@ public WelshPowell(String attrName) {
}

/**
* New Welsh and Powell coloring algorithm, using "WelshPowell.color" as the attribute
* name.
* New Welsh and Powell coloring algorithm, using "WelshPowell.color" as the
* attribute name.
*
*/
public WelshPowell() {
Expand Down Expand Up @@ -251,7 +221,6 @@ public void setAttributeName(String attrName) {
this.attrName = attrName;
}


/*
* (non-Javadoc)
*
Expand All @@ -277,84 +246,53 @@ public void compute() {
// the algorithm requires the use of a sorted list using
// degree values for sorting them.

Comparator<Node> degreeComparator = new Comparator<Node>() {
public int compare(Node ni, Node nj) {
int returnValue = 0;
int diff = ni.getDegree() - nj.getDegree();

if (diff > 0) {
returnValue = -1;
} else if (diff < 0) {
returnValue = 1;
}
LinkedList<Node> sortedNodes = new LinkedList<Node>();
FibonacciHeap<Integer, Node> heap = new FibonacciHeap<Integer, Node>();

return returnValue;
}
};

PriorityQueue<Node> pq = new PriorityQueue<Node>(g.getNodeCount(),
degreeComparator);
Iterator<? extends Node> nodes = g.getNodeIterator();

while (nodes.hasNext()) {
pq.add(nodes.next());
for (int i = 0; i < g.getNodeCount(); i++) {
Node n = g.getNode(i);
heap.add(n.getDegree(), n);
}

ArrayList<Node> sortedNodes = new ArrayList<Node>();
while (!heap.isEmpty())
sortedNodes.addFirst(heap.extractMin());

for (int i = 0; i < g.getNodeCount(); i++) {
sortedNodes.add(pq.poll());
}
heap = null;

// ------ STEP 2 --------
// color initialization

ArrayList<Integer> allColors = new ArrayList<Integer>();
Integer col;
int nbColors = 0;

for (int i = 0; i < g.getNodeCount(); i++) {
col = i;
allColors.add(col);
}

// ------- STEP 3 --------

Integer currentColor = allColors.remove(0);
nbColors++;
while (sortedNodes.size() > 0) {
Node root = sortedNodes.poll();
LinkedList<Node> myGroup = new LinkedList<Node>();
myGroup.add(root);

while (!sortedNodes.isEmpty()) {
int index = 0;
root.addAttribute(attributeName, nbColors);

while (index < sortedNodes.size()) {
Node n = sortedNodes.get(index);
Iterator<? extends Node> neighbors = n
.getNeighborNodeIterator();
for (int i = 0; i < sortedNodes.size();) {
Node p = sortedNodes.get(i);
boolean conflict = false;

while (neighbors.hasNext() && !conflict) {
Node neighb = neighbors.next();

if (neighb.hasAttribute(attributeName)) {
if (((neighb.getAttribute(attributeName)))
.equals(currentColor)) {
conflict = true;
}
}
}
for (int j = 0; !conflict && j < myGroup.size(); j++)
conflict = p.getEdgeBetween(myGroup.get(j).getIndex()) != null;

if (!conflict) {
n.addAttribute(attributeName, currentColor);
sortedNodes.remove(index);
} else {
index++;
if (conflict)
i++;
else {
p.addAttribute(attributeName, nbColors);
myGroup.add(p);
sortedNodes.remove(i);
}
}

currentColor = allColors.remove(0);
myGroup.clear();
nbColors++;
}

chromaticNumber = nbColors-1;
chromaticNumber = nbColors;
}
}

0 comments on commit a07ee7a

Please sign in to comment.