001    package edu.wwu.tobikley.acgc.algorithms;
002    
003    import java.math.BigInteger;
004    
005    import java.util.HashMap;
006    import java.util.Iterator;
007    
008    import edu.uci.ics.jung.graph.Edge;
009    import edu.uci.ics.jung.graph.Graph;
010    import edu.uci.ics.jung.graph.Vertex;
011    
012    
013    /**
014     * Implements a Naive Counting Algorithm as a <code>CountingAlgorithm</code>.
015     * To determine the exact number of proper q-Colorings the following steps
016     * are performed:
017     * 
018     * <ol>
019     * <li>Collect all vertices in an ordered fashion.
020     * <li>Then go throught the induced list of alle q-Colorings
021     *     (there are q^k of them) in lexicographic order.
022     * <li>For each q-Coloring decide if it is proper and count it,
023     *     if it is.
024     * </ol>
025     *  
026     * For further information, refer to
027     * 
028     * <ul>
029     * <li> Häggström, O.: Finite Markov Chains and Algorithmic Applications,
030     *      Cambridge u. a.: Cambridge Univ. Press 2002, p. 65.
031     * </ul>
032     * 
033     * @version 1.0
034     * @author  Tobias Kley
035     */
036    public class NaiveCountingAlgorithm extends CountingAlgorithm {
037            
038            /** The current coloring checked by the algorithm. */
039            private int[] coloring = null;
040            
041            /** Specified position in <code>coloring</code> to watch for changes
042             *  to report progress. The position is chosen, so that there are least
043             *  possible but at last 100 changes in color. */
044            private int watchIndex = 0;
045            
046            /** Color previously watched at the <code>watchIndex</code> of
047             *  <code>coloring</code>.*/
048            private int watchedColor = 0;
049            
050            /** Mapping the graphs vertices to Integer ids. */
051            protected HashMap<Vertex,Integer> verticeNames = null;
052    
053            /**
054             * Creates a new instance of a naive counting algorithm.
055             * Invokes the constructor of <code>CountingAlgorithm</code> and
056             * initializes <code>verticeNames</code> and the <code>watchIndex</code>.
057             * 
058             * @param g The graph to calculate the number of q-Colorings from.
059             * @param numberOfColors The number q as the question is: How many q-Colorings are there.
060             */
061            public NaiveCountingAlgorithm(Graph g, int numberOfColors) {
062                    super(g, numberOfColors);
063                    
064                    // Knoten durchnummerieren.
065                    this.verticeNames = new HashMap<Vertex,Integer>(g.numVertices());
066                    Integer i = 0;
067                    Iterator verticeIterator = g.getVertices().iterator();
068                    while (verticeIterator.hasNext()) {
069                            verticeNames.put((Vertex)verticeIterator.next(), i++);
070                    }
071                    
072                    if(Math.ceil(Math.log(100)/Math.log(numberOfColors)) > 0) {
073                            watchIndex = Math.max(0,g.numVertices() - (int)Math.ceil(Math.log(100)/Math.log(numberOfColors)));
074                    }
075            }
076    
077            /**
078             * Checks if a q-Coloring is proper regarding the
079             * <code>graphWorkingCopy</code>.
080             * To determine if it is a proper q-Colorings, each edge in the graph is
081             * examined. A coloring is proper if the endnodes of all edges are of
082             * different colors.
083             * 
084             * @return <code>true</code> if <code>coloring</code> is a proper q-Coloring, and
085             *         <code>false</code> if it is not.
086             */
087            private boolean isProperVertexColoring() {
088                    boolean result = true;
089                    Iterator edgeIterator = graphWorkingCopy.getEdges().iterator();
090                    while (edgeIterator.hasNext()) {
091                            Edge e = (Edge)edgeIterator.next();
092                            int i = verticeNames.get(e.getEndpoints().getFirst()).intValue();
093                            int j = verticeNames.get(e.getEndpoints().getSecond()).intValue();
094                            if (coloring[i] == coloring[j]) {
095                                    result = false;
096                            }
097                    }
098                    return result;
099            }
100            
101            /**
102             * Iterates through all possible q-Colorings and calls <code>isValid</code>
103             * to determine if it is proper. Before the coloring is checked,
104             * <code>setProgress</code> is called, to propagate the progress of the
105             * calculation.
106             */
107            public void algorithm() {
108                    //lokale Variablen initialisieren
109                    returnVal = new BigInteger("0");
110                    coloring = new int[graphWorkingCopy.numVertices()];
111                    for (int i = 0; i < coloring.length; i++) {
112                            coloring[i] = 1;
113                    }
114                    coloring[0]=0;
115                    int i = 0;
116                    
117                    do {
118                            if (coloring[i] < numberOfColors) {
119                                    
120                                    coloring[i]++;
121                                    while(i > 0){
122                                            i--;
123                                            coloring[i]=1;
124                                    }
125                                    setProgress();
126                                    boolean isValid = isProperVertexColoring();
127                                    if (isValid) {
128                                            returnVal = returnVal.add(BigInteger.ONE);
129                                    }
130                            } else {
131                                    i++;
132                            }
133                            
134                    } while (i < coloring.length);
135                    detailedResults.add(new CountingResult("Exact",returnVal,System.currentTimeMillis()-startTime));
136            }
137            
138            /**
139             * If necessary <code>progress</code> and <code>progressText</code> are updated.
140             * The <code>progressText</code> is set to the text: "Calculation is xx% finished.".
141             */
142            private synchronized void setProgress() {
143                    if(coloring[watchIndex] != watchedColor) {
144                            watchedColor = coloring[watchIndex];
145                            progress = 0;
146                            for (int i = watchIndex; i < coloring.length; i++) {
147                                    progress += (coloring[i]-1)*(Math.pow(numberOfColors,(i-watchIndex)));
148                            }
149                            progress = (int) (100*progress/(Math.pow(numberOfColors,coloring.length-watchIndex)));
150                            setProgressText("Calculation is "+progress+"% finished.");
151                    }
152            }
153    
154            /**
155             * @param progressText
156             */
157            private synchronized void setProgressText(String progressText){
158                    this.progressText = progressText;
159            }
160    
161    
162    }