1 pnkfelix 1.1.2.1  // SimpleGraphColorer.java, created Wed Jan 13 14:17:43 1999 by pnkfelix
  2 cananian 1.1.2.18 // Copyright (C) 1998 Felix S. Klock II <pnkfelix@mit.edu>
  3 cananian 1.1.2.7  // Licensed under the terms of the GNU GPL; see COPYING for details.
  4 pnkfelix 1.1.2.1  package harpoon.Analysis.GraphColoring;
  5 pnkfelix 1.1.2.1  
  6 pnkfelix 1.1.2.8  import java.util.List;
  7 pnkfelix 1.1.2.10 import java.util.Iterator;
  8 pnkfelix 1.1.2.10 import java.util.Collection;
  9 pnkfelix 1.1.2.10 import java.util.ArrayList;
 10 pnkfelix 1.1.2.10 import java.util.HashSet;
 11 pnkfelix 1.1.2.6  import java.util.Vector;
 12 pnkfelix 1.1.2.6  import java.util.Stack;
 13 pnkfelix 1.1.2.6  import java.util.Enumeration;
 14 pnkfelix 1.1.2.1  
 15 pnkfelix 1.1.2.10 import harpoon.Util.Util;
 16 cananian 1.3      import net.cscott.jutil.LinearSet;
 17 pnkfelix 1.1.2.10 
 18 pnkfelix 1.1.2.1  /**
 19 pnkfelix 1.1.2.16  * <code>SimpleGraphColorer</code> uses the simple but effective graph
 20 pnkfelix 1.1.2.16  * coloring strategy of progressively removing nodes with degree less
 21 pnkfelix 1.1.2.16  * than K, (where K is the number of colors provided).  This is a
 22 pnkfelix 1.1.2.16  * conservative heuristic, as it guarantees that if the graph
 23 pnkfelix 1.1.2.16  * post-removal is K-colorable, then the graph post-replacement will
 24 pnkfelix 1.1.2.16  * also K-colorable; several improvements on this heuristic are
 25 pnkfelix 1.1.2.16  * available. 
 26 pnkfelix 1.1.2.16  * Inspired by a 6.035 
 27 pnkfelix 1.1.2.16  * <A href="http://ceylon.lcs.mit.edu/6035/lecture18/sld064.htm">lecture</A>.
 28 pnkfelix 1.1.2.1   * 
 29 cananian 1.1.2.18  * @author  Felix S. Klock II <pnkfelix@mit.edu>
 30 cananian 1.4       * @version $Id: SimpleGraphColorer.java,v 1.4 2004/02/08 03:19:33 cananian Exp $
 31 pnkfelix 1.1.2.1   */
 32 pnkfelix 1.1.2.1  
 33 pnkfelix 1.1.2.4  public class SimpleGraphColorer extends GraphColorer {
 34 pnkfelix 1.1.2.2  
 35 pnkfelix 1.1.2.3      private static final boolean DEBUG = false;
 36 pnkfelix 1.1.2.5  
 37 pnkfelix 1.1.2.10     public SimpleGraphColorer() { }
 38 pnkfelix 1.1.2.1      
 39 pnkfelix 1.1.2.16     /** Colors <code>graph</code>.
 40 pnkfelix 1.1.2.16      */
 41 pnkfelix 1.1.2.10     public final void color(ColorableGraph graph, List colors) 
 42 pnkfelix 1.1.2.11         throws UnableToColorGraph {
 43 pnkfelix 1.1.2.10         // System.out.println("entered color("+graph+", "+colors+")");
 44 pnkfelix 1.1.2.10 
 45 pnkfelix 1.1.2.10         boolean moreNodesToHide = false;
 46 pnkfelix 1.1.2.10         do {
 47 pnkfelix 1.1.2.10             moreNodesToHide = false;
 48 pnkfelix 1.1.2.10             
 49 pnkfelix 1.1.2.10             // make new copy of nodeSet (can't modify graph and
 50 pnkfelix 1.1.2.10             // iterate over it at same time)
 51 pnkfelix 1.1.2.10             HashSet nodeSet = new HashSet(graph.nodeSet());
 52 pnkfelix 1.1.2.10             Iterator nodes = nodeSet.iterator();
 53 pnkfelix 1.1.2.10             while(nodes.hasNext()) {
 54 pnkfelix 1.1.2.10                 Object n = nodes.next();
 55 pnkfelix 1.1.2.10                 if (graph.getDegree( n ) < colors.size() ) {
 56 pnkfelix 1.1.2.10                     graph.hide(n);
 57 pnkfelix 1.1.2.10                     
 58 pnkfelix 1.1.2.10                     // removing n may have made previous nodes in
 59 pnkfelix 1.1.2.10                     // the enumeration available to be hidden 
 60 pnkfelix 1.1.2.10                     moreNodesToHide = true;
 61 pnkfelix 1.1.2.10                 }
 62 pnkfelix 1.1.2.10             }
 63 pnkfelix 1.1.2.10         } while(moreNodesToHide);
 64 pnkfelix 1.1.2.10         
 65 pnkfelix 1.1.2.10         // at this point, we are assured that there are no more
 66 pnkfelix 1.1.2.10         // nodes to hide.  Either the graph is finished (no nodes
 67 pnkfelix 1.1.2.10         // remain) or all nodes present have degree >=
 68 pnkfelix 1.1.2.10         // colors.size(), in which case this algorithm can't color
 69 pnkfelix 1.1.2.10         // it without more colors.
 70 pnkfelix 1.1.2.10         if (!graph.nodeSet().isEmpty()) {
 71 pnkfelix 1.1.2.17             UnableToColorGraph u = new UnableToColorGraph();
 72 pnkfelix 1.1.2.17             u.rmvSuggs = new LinearSet(graph.nodeSet());
 73 pnkfelix 1.1.2.17             throw u;
 74 pnkfelix 1.1.2.10         }
 75 pnkfelix 1.1.2.10         
 76 pnkfelix 1.1.2.17         nextNode:
 77 pnkfelix 1.1.2.10         for(Object n=graph.replace(); n!=null; n=graph.replace()){
 78 pnkfelix 1.1.2.10             // find color that none of n's neighbors is set to
 79 pnkfelix 1.1.2.12 
 80 pnkfelix 1.1.2.14             if (graph.getColor(n) != null) {
 81 pnkfelix 1.1.2.14                 // precolored, skip
 82 pnkfelix 1.1.2.15                 if (false) 
 83 pnkfelix 1.1.2.15                     System.out.println("skipping "+n+
 84 pnkfelix 1.1.2.15                                        "b/c its precolored to "+
 85 pnkfelix 1.1.2.15                                        graph.getColor(n));
 86 pnkfelix 1.1.2.17                 continue nextNode;
 87 pnkfelix 1.1.2.14             }
 88 pnkfelix 1.1.2.14 
 89 pnkfelix 1.1.2.12             Collection nborsC = graph.neighborsOf(n);
 90 pnkfelix 1.1.2.12             HashSet nColors = new HashSet(nborsC.size());
 91 pnkfelix 1.1.2.12             for(Iterator nbors = nborsC.iterator(); nbors.hasNext();){
 92 pnkfelix 1.1.2.12                 Object nb = nbors.next();
 93 pnkfelix 1.1.2.10                 nColors.add(graph.getColor(nb));
 94 pnkfelix 1.1.2.10             }
 95 pnkfelix 1.1.2.10             
 96 cananian 1.4                  for(Object colO : colors){
 97 cananian 1.4                      Color col = (Color) colO;
 98 pnkfelix 1.1.2.10                 if (!nColors.contains(col)) {
 99 pnkfelix 1.1.2.17                     try {
100 pnkfelix 1.1.2.17                         graph.setColor(n, col);
101 pnkfelix 1.1.2.17                         continue nextNode;
102 pnkfelix 1.1.2.17                     } catch (ColorableGraph.IllegalColor ic) {
103 pnkfelix 1.1.2.17                         // col was not legal for n
104 pnkfelix 1.1.2.17                         // try another color...
105 pnkfelix 1.1.2.17                     }
106 pnkfelix 1.1.2.10                 }
107 pnkfelix 1.1.2.10             }
108 pnkfelix 1.1.2.10             
109 pnkfelix 1.1.2.17             // if we ever reach this point, we failed to color n
110 pnkfelix 1.1.2.17             UnableToColorGraph u = new UnableToColorGraph();
111 pnkfelix 1.1.2.17             u.rmvSuggs = new LinearSet(graph.nodeSet()); 
112 pnkfelix 1.1.2.17             throw u;
113 pnkfelix 1.1.2.10         }
114 pnkfelix 1.1.2.10     }
115 pnkfelix 1.1.2.10 
116 cananian 1.2      }