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 Lesser General Public License (LGPL): http://www.gnu.org/licenses/
004    
005    package graphlab.library.algorithms.graphdecomposition;
006    
007    import graphlab.library.BaseEdge;
008    import graphlab.library.BaseGraph;
009    import graphlab.library.BaseVertex;
010    import graphlab.library.algorithms.Algorithm;
011    import graphlab.library.algorithms.AutomatedAlgorithm;
012    import graphlab.library.algorithms.util.EventUtils;
013    import graphlab.library.event.GraphRequest;
014    import graphlab.library.util.Pair;
015    
016    import java.util.Iterator;
017    import java.util.Stack;
018    import java.util.Vector;
019    
020    /**
021     * This Method find the biconnected components of a
022     * graph.
023     * Which are the maximal subgraphs without any cut vertices.
024     *
025     * @author Soroush Sabet
026     */
027    public class BiconnectedComponents
028            <VertexType extends BaseVertex, EdgeType extends BaseEdge<VertexType>>
029            extends Algorithm implements AutomatedAlgorithm {
030        //PreWorkPostWorkHandler handler = new PreWorkPostWorkHandler<VertexType>();
031        Integer[] DFS_N;
032        Integer[] High;
033        int[] Parent;
034        Vector<Pair<Vector<VertexType>, Vector<EdgeType>>> BiC = new Vector<Pair<Vector<VertexType>, Vector<EdgeType>>>();
035    
036        int DFSn;
037        private VertexType root;
038    
039        /**
040         * The initialization, before searching for biconnected
041         * components.
042         * Here, DFSn is the number assigned to vertices in process
043         * of dfs traversal, although in decreasing order.
044         * High[v] denotes the highest vertex, reachable from v or
045         * it's children in the dfs tree.
046         *
047         * @param g is the input graph.
048         */
049        private void init(BaseGraph<VertexType, EdgeType> g) {
050            DFS_N = new Integer[g.getVerticesCount()];
051            for (int i = 0; i < g.getVerticesCount(); i++)
052                DFS_N[i] = 0;
053    
054            DFSn = g.getVerticesCount();
055            High = new Integer[g.getVerticesCount()];
056            Parent = new int[g.getVerticesCount()];
057        }
058    
059        public void doAlgorithm() {
060            GraphRequest<VertexType, EdgeType> gr = new GraphRequest<VertexType, EdgeType>();
061            dispatchEvent(gr);
062            BaseGraph<VertexType, EdgeType> g = gr.getGraph();
063            this.Bicon(g);
064        }
065    
066        /**
067         * This class is used to put both vertices and edges in
068         * a stack.
069         */
070        private class VE {
071    
072            VertexType v;
073            EdgeType e;
074    
075            VE(VertexType v) {
076                this.v = v;
077                this.e = null;
078            }
079    
080            VE(EdgeType e) {
081                this.e = e;
082                this.v = null;
083            }
084    
085            VE() {
086                this.v = null;
087                this.e = null;
088            }
089        }
090    
091        int rootChilds = 0;
092        int foundDecompositions;
093        Stack<VE> S = new Stack<VE>(); //stack is initially empty
094    
095        /**
096         * This method is in fact dfs, with some preworks and postworks
097         * added to it.
098         * It finds biconnected components of the input graph g, by
099         * starting search from the node v.
100         *
101         * @param g
102         * @param v
103         */
104        private void BC(BaseGraph<VertexType, EdgeType> g, VertexType v) {
105            DFS_N[v.getId()] = DFSn;
106            DFSn--;
107            S.push(new VE(v));
108            High[v.getId()] = DFS_N[v.getId()];
109    
110            Iterator<EdgeType> iet;
111            iet = g.edgeIterator(v);
112    
113            EdgeType edge;
114            VertexType w;
115    //        BaseGraph<VertexType,EdgeType> g1;
116    
117            while (iet.hasNext()) {
118                edge = iet.next();
119                w = edge.source == v ? edge.target : edge.source;
120    //            if (edge.getRGBColor()==0)
121    //                S.push(new VE(edge)); //each edge will be inserted twice (for both directions)
122    
123                if (Parent[v.getId()] != w.getId())
124                    if (DFS_N[w.getId()] == 0) { //w not visited before
125                        Parent[w.getId()] = v.getId();
126                        edge.setMark(true);
127                        w.setMark(true);
128                        EventUtils.algorithmStep(this, "");
129                        BC(g, w);
130                        w.setMark(false);
131                        EventUtils.algorithmStep(this, "");
132                        if (High[w.getId()] <= DFS_N[v.getId()]) { //v disconnects w from the rest of the graph
133                            if (v == root) {
134                                //the root is an articulation point if and only if it has more than one child in the DFS tree
135                                rootChilds++;
136                                if (rootChilds == 1)
137                                    continue;
138                            }
139                            foundDecompositions++;
140                            //VE SObj = new VE();
141                            //Vector<VertexType> ov = new Vector<VertexType>();
142                            //Vector<EdgeType> oe = new Vector<EdgeType>();
143                            v.setColor(2);
144                            //the stact has problems, put it for later correction
145    //                        while (SObj.v != v) {
146    //                            //remove all edges and vertices from stack until v is reached, and mark the subgraph they form as a biconnected component
147    //                            SObj = S.pop();
148    //                            if (SObj.v != null) {
149    //                                SObj.v.setColor(foundDecompositions);
150    //                                ov.add(SObj.v);
151    //                            } else {
152    //                                EdgeType e = SObj.e;
153    ////                                if (){
154    //                                    SObj.e.setColor(foundDecompositions);
155    //                                    oe.add(SObj.e);
156    ////                                }
157    //                            }
158    //                        EventUtils.algorithmStep(this,600);
159    //                        }
160    //                        BiC.add(new Pair<Vector<VertexType>, Vector<EdgeType>>(ov, oe));
161    //                        S.add(new VE(v));//v is part of w's component and possibly others
162                        }
163                        High[v.getId()] = Math.max(High[v.getId()], High[w.getId()]);
164    //                    if (High[w.getId()] > High[v.getId()])
165    //                        High[v.getId()] = High[w.getId()];
166                    } else   //(v,w) is a back edge or a forward edge
167                        High[v.getId()] = Math.max(High[v.getId()], DFS_N[w.getId()]);
168            }
169    //        dispatchEvent(new VertexEdgeLabelEvent<VertexType, EdgeType>(DFS_N[v.getId()] + ":" + High[v.getId()], v));
170        }
171    
172    
173        /**
174         * This is the main method, wich take the graph g as
175         * the input, and returns the biconnected components
176         * of g in a vector.
177         *
178         * @param g
179         */
180        public Vector<Pair<Vector<VertexType>, Vector<EdgeType>>> Bicon(BaseGraph<VertexType, EdgeType> g) {
181    //    public Vector<BaseGraph<VertexType,EdgeType>> Bicon(BaseGraph<VertexType,EdgeType> g){
182            init(g);
183            VertexType v = g.iterator().next();
184            rootChilds = 0;
185            root = v;
186            foundDecompositions = 0;
187            BC(g, v);
188            return BiC;
189    
190        }
191    }