001    // GraphLab Project: http://graphlab.sharif.edu
002    // Copyright (C) 2008 Mathematical Science Department of Sharif University of Technology
003    // Distributed under the terms of the GNU General Public License (GPL): http://www.gnu.org/licenses/
004    
005    package graphlab.extensions.reports;
006    
007    import graphlab.graph.graph.VertexModel;
008    import graphlab.library.BaseEdge;
009    import graphlab.library.BaseGraph;
010    import graphlab.library.BaseVertex;
011    
012    import java.util.ArrayDeque;
013    import java.util.Iterator;
014    import java.util.LinkedList;
015    
016    /**
017     * generates all partitionings of the given graph with t or less partitions
018     * which in each partition does not have any edges
019     *
020     * @author Azin Azadi
021     */
022    public class Partitioner {
023        public BaseVertex[] vertices;
024        public int[][] edgeArray;
025        public int[] color;
026        private BaseGraph g;
027    
028    
029        public Partitioner(final BaseGraph g) {
030            this.g = g;
031            edgeArray = g.getEdgeArray();
032            vertices = g.getVertexArray();
033        }
034    
035        public boolean findAllSubsets(SubSetListener listener) {
036            color = new int[vertices.length];
037    
038            ArrayDeque<BaseVertex> v = new ArrayDeque<BaseVertex>();
039            for (BaseVertex _ : g.getVertexArray()) {
040                v.add(_);
041            }
042    
043            return findAllSubsetsRecursively(1, listener, v, new ArrayDeque<BaseVertex>(), new ArrayDeque<BaseVertex>());
044        }
045    
046        public int findMaxIndSet(boolean putFirstVertexInSet) {
047            color = new int[vertices.length];
048    
049            v = new ArrayDeque<BaseVertex>();
050            set = new boolean[g.getVerticesCount()];
051            int i = 0;
052            for (BaseVertex _ : g.getVertexArray()) {
053                v.add(_);
054                set[i++] = false;
055            }
056            maxSet = Integer.MIN_VALUE;
057    
058    //        curRejectedFromSet = 0;
059    //        minRejectedFromSet = Integer.MAX_VALUE;
060    
061            curSet = 0;
062            int start = 0;
063    //        putFirstVertexInSet = false;
064            if (putFirstVertexInSet) {
065                curSet = 1;
066                set[0] = true;
067                v.remove(vertices[0]);
068                for (int ii : edgeArray[0]) {
069                    v.remove(vertices[ii]);
070                }
071            }
072    
073            V = new VertexModel[v.size()];
074            N = v.size();
075            v.toArray(V);
076    
077            ID = new int[vertices.length];
078            for (i = 0; i < vertices.length; i++) {
079                ID[i] = vertices[i].getId();
080            }
081            mark = new boolean[vertices.length];
082            found = 0;
083            findMaxIndSetsRecursively(0);
084            System.out.println(found + " , iter:" + iter);
085            return maxSet;
086        }
087    
088        boolean set[];
089        boolean mark[];
090    //    boolean markbck[];
091    
092        VertexModel[] V;
093        int ID[];
094        int N;
095        ArrayDeque<BaseVertex> v;
096        int maxSet = Integer.MIN_VALUE;
097        int curSet;
098        //    int curRejectedFromSet;
099        //    int minRejectedFromSet;
100        int found = 0;
101        int iter = 0;
102    
103        int i;
104    
105        private void findMaxIndSetsRecursively(int iv) {
106            while (iv < N && mark[iv]) {
107                iv++;
108            }
109            iter++;
110            if (curSet + (N - iv) < maxSet) {
111                return;
112            }
113            if (iv >= N) {
114                if (curSet > maxSet) {
115                    maxSet = curSet;
116                    found++;
117                    System.out.println("A" + maxSet);
118                }
119    //            }
120                return;
121            }
122    
123            int vid = V[iv].getId();
124            //set and backup marks
125            int[] nv = edgeArray[vid];
126            int ss = nv.length;
127    
128            boolean markbck[] = new boolean[ss];
129            for (i = 0; i < ss; i++) {
130                markbck[i] = mark[nv[i]];
131                mark[nv[i]] = true;
132            }
133    
134            //put vid in set
135            int iiv = iv + 1;
136            while (iiv < N && mark[iiv]) {
137                iiv++;
138            }
139    
140            set[vid] = true;
141            curSet++;
142            /*****************************/
143            findMaxIndSetsRecursively(iiv);
144            /*****************************/
145            curSet--;
146            set[vid] = false;
147    
148    
149            for (i = 0; i < ss; i++) {
150                mark[nv[i]] = markbck[i];
151            }
152            //BackTrak on complement
153            iiv = iv + 1;
154            while (iiv < N && mark[iiv]) {
155                iiv++;
156            }
157            /*****************************/
158            findMaxIndSetsRecursively(iiv);
159            /*****************************/
160        }
161    
162    
163        public boolean findAllPartitionings(final int t, final ColoringListener listener) {
164            color = new int[vertices.length];
165    
166            ArrayDeque<BaseVertex> v = new ArrayDeque<BaseVertex>();
167            for (BaseVertex _ : g.getVertexArray()) {
168                v.add(_);
169            }
170            if (findAllPartitioningsRecursively(t, new ColoringListener() {
171                public boolean coloringFound(final int t) {
172                    if (checkColoring(g)) {
173                        boolean b = listener.coloringFound(t);
174                        return b;
175                    }
176                    return false;
177                }
178            }, v)) return true;
179            return false;
180        }
181    
182        public boolean findAllPartitioningsRecursively(final int tt, final ColoringListener listener, final ArrayDeque<BaseVertex> v) {
183            if (tt == 0 || v.size() == 0) {
184                return listener.coloringFound(tt);
185            }
186            BaseVertex fv = v.removeFirst();
187            color[fv.getId()] = tt;
188    
189    //inkedList<BaseVertex> _v = new LinkedList<BaseVertex>(v);
190            ArrayDeque<BaseVertex> compl = new ArrayDeque<BaseVertex>();
191            if (findAllSubsetsRecursively(tt, new SubSetListener() {
192                LinkedList<BaseVertex> vert = new LinkedList<BaseVertex>();
193    
194                public boolean subsetFound(final int t, ArrayDeque<BaseVertex> complement, ArrayDeque<BaseVertex> set) {
195                    return findAllPartitioningsRecursively(tt - 1, listener, complement);
196                }
197            }
198                    , v, new ArrayDeque<BaseVertex>(), compl)) return true;
199            color[fv.getId()] = 0;
200            v.addFirst(fv);
201            return false;
202        }
203    
204        private boolean findAllSubsetsRecursively(final int t, SubSetListener listener, ArrayDeque<BaseVertex> v, ArrayDeque<BaseVertex> set, ArrayDeque<BaseVertex> complement) {
205            if (t == 0 || v.size() == 0) {
206                //all colorings of valid and checked before except the remaining vertices which all have color 0
207                for (BaseVertex _v : v) {
208                    for (int i : edgeArray[_v.getId()])
209                        if (color[i] == 0)
210                            return false;
211                }
212                //so it is a valid partitioning (coloring)
213                if (listener.subsetFound(t, complement, set)) return true;
214                return false;
215            }
216            BaseVertex _ = v.removeFirst();
217    
218            boolean canColoredT = true;
219            for (int i : edgeArray[_.getId()]) {
220                if (color[i] == t) {
221                    canColoredT = false;
222                    break;
223                }
224            }
225            if (canColoredT) {
226                color[_.getId()] = t;
227                set.add(_);
228                if (findAllSubsetsRecursively(t, listener, v, set, complement)) return true;
229                set.remove(_);
230            }
231    
232            color[_.getId()] = 0;
233            complement.add(_);
234            if (findAllSubsetsRecursively(t, listener, v, set, complement)) return true;
235            complement.remove(_);
236            v.addFirst(_);
237            return false;
238        }
239    
240        /**
241         * @param g
242         * @return true if the coloring of g is a valid vertex coloring
243         */
244        public boolean checkColoring(BaseGraph g) {
245            Iterator<BaseEdge> ie = g.edgeIterator();
246            while (ie.hasNext()) {
247                BaseEdge e = ie.next();
248                if (color[e.source.getId()] == color[e.target.getId()]) {
249                    return false;
250                }
251            }
252            return true;
253        }
254    
255    }