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 }