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.plugins.main.core; 006 007 import graphlab.graph.graph.GraphPoint; 008 import graphlab.graph.graph.VertexModel; 009 import graphlab.library.BaseEdge; 010 import graphlab.library.BaseGraph; 011 import graphlab.library.BaseVertex; 012 import graphlab.library.Path; 013 import graphlab.library.algorithms.util.LibraryUtils; 014 015 import java.awt.geom.Point2D; 016 import java.awt.geom.Rectangle2D; 017 import java.util.ArrayList; 018 import java.util.Collection; 019 import java.util.Iterator; 020 import java.util.Vector; 021 022 /** 023 * Just some methods helping you to write Graph Algorithms easier, 024 * 025 * @see graphlab.library.algorithms.util.LibraryUtils 026 */ 027 public class AlgorithmUtils { 028 public final static int Max_Int = 2100000000; 029 030 031 /** 032 * sets all vertex colors to 0. 033 */ 034 public static void resetVertexColors(BaseGraph<BaseVertex, BaseEdge<BaseVertex>> g) { 035 for (BaseVertex v : g) { 036 v.setColor(0); 037 } 038 } 039 040 /** 041 * sets all vertex marks to false 042 */ 043 public static void resetVertexMarks(BaseGraph<BaseVertex, BaseEdge<BaseVertex>> g) { 044 for (BaseVertex v : g) { 045 v.setMark(false); 046 } 047 } 048 049 /** 050 * determines wether g is connected or not 051 */ 052 public static <VertexType extends BaseVertex, EdgeType extends BaseEdge<VertexType>> 053 boolean isConnected(BaseGraph<VertexType, EdgeType> g) { 054 ArrayList vs = new ArrayList(); 055 int[] parent = new int[g.getVerticesCount()]; 056 dfs(g, 0, vs, parent); 057 return vs.size() == g.getVerticesCount(); 058 } 059 060 /** 061 * determines wether g is complete or not 062 */ 063 public static <VertexType extends BaseVertex, EdgeType extends BaseEdge<VertexType>> 064 boolean isCompleteGraph(BaseGraph<VertexType, EdgeType> g) { 065 int size = g.getVerticesCount(); 066 for (int i : getDegreesList(g)) 067 if (i != size - 1) 068 return false; 069 return true; 070 } 071 072 /** 073 * returns the adjacency list of g. 074 * 075 * @deprecated use BaseGraph.getEdgeArray instead 076 */ 077 public static <VertexType extends BaseVertex, EdgeType extends BaseEdge<VertexType>> 078 ArrayList<ArrayList<Integer>> getAdjList(BaseGraph<VertexType, EdgeType> g) { 079 double[][] mat = g.getAdjacencyMatrix().getArray(); 080 ArrayList<ArrayList<Integer>> alist = new ArrayList(); 081 int vCount = mat.length; 082 for (int i = 0; i < vCount; i++) { 083 ArrayList<Integer> adjacencyList = new ArrayList(); 084 for (int j = 0; j < vCount; j++) 085 if (mat[i][j] == 1) 086 adjacencyList.add(j); 087 alist.add(adjacencyList); 088 } 089 return alist; 090 } 091 092 /** 093 * returns the degree of the node with the id 094 * @deprecated 095 096 * @see graphlab.library.BaseGraph#getDegree(graphlab.library.BaseVertex) 097 */ 098 public static <VertexType extends BaseVertex, EdgeType extends BaseEdge<VertexType>> 099 int getDegree(BaseGraph<VertexType, EdgeType> bg, int node) { 100 int result = 0; 101 double[][] mat = bg.getAdjacencyMatrix().getArray(); 102 int vCount = mat.length; 103 if (node > vCount) 104 return -1; 105 for (int i = 0; i < vCount; i++) 106 if (mat[node][i] == 1) 107 result++; 108 109 return result; 110 111 } 112 113 /** 114 * returns all neighbors of the given vertex 115 * @deprecated 116 * @see graphlab.library.BaseGraph#getNeighbors(graphlab.library.BaseVertex) 117 */ 118 public static <VertexType extends BaseVertex, EdgeType extends BaseEdge<VertexType>> 119 ArrayList<VertexType> getNeighbors(BaseGraph<VertexType, EdgeType> g, VertexType source) { 120 ArrayList<VertexType> ret = new ArrayList<VertexType>(); 121 Iterator<EdgeType> ie = g.edgeIterator(source); 122 while (ie.hasNext()) { 123 EdgeType e = ie.next(); 124 if (e.target == source && !ret.contains(e.source)) 125 ret.add(e.source); 126 if (e.source == source && !ret.contains(e.target)) 127 ret.add(e.target); 128 } 129 return ret; 130 } 131 132 /** 133 * returns all neighbors of the given vertex 134 * @deprecated 135 * @see graphlab.library.BaseGraph#getNeighbors(graphlab.library.BaseVertex) 136 */ 137 public static <VertexType extends BaseVertex, EdgeType extends BaseEdge<VertexType>> 138 ArrayList<VertexType> getNeighbors2(BaseGraph<VertexType, EdgeType> g, VertexType source) { 139 ArrayList<VertexType> ret = new ArrayList<VertexType>(); 140 Iterator<EdgeType> ie = g.edgeIterator(source); 141 while (ie.hasNext()) { 142 EdgeType e = ie.next(); 143 // if (e.target == source && !ret.contains(e.source)) 144 // ret.add(e.source); 145 if (e.source == source && !ret.contains(e.target)) 146 ret.add(e.target); 147 } 148 return ret; 149 } 150 151 /** 152 * returns a path from source to target 153 * path.get(0) = dest 154 */ 155 public static <VertexType extends BaseVertex, EdgeType extends BaseEdge<VertexType>> 156 Path<VertexType> getPath(BaseGraph<VertexType, EdgeType> g, VertexType source, VertexType dest) { 157 boolean vertexMarksBackup[] = LibraryUtils.getVertexMarks(g); 158 clearVertexMarks(g); 159 Vector<VertexType> q = new Vector<VertexType>(); 160 q.add(source); 161 source.setMark(true); 162 163 BaseVertex[] parents = new BaseVertex[g.getVerticesCount()]; 164 boolean found = false; 165 while (!q.isEmpty() && !found) { 166 VertexType v = q.remove(0); 167 168 for (VertexType _ : getNeighbors(g, v)) { 169 if (_ == dest) { 170 found = true; 171 // break; 172 } 173 if (!_.getMark()) { 174 q.add(_); 175 _.setMark(true); 176 parents[_.getId()] = v; 177 } 178 } 179 } 180 181 if (!found) { 182 return null; 183 } 184 185 //extract the path 186 Path<VertexType> ret = new Path<VertexType>(); 187 188 int _ = dest.getId(); 189 ret.insert(dest); 190 while (_ != source.getId()) { 191 // System.out.println("_=" + _); 192 193 ret.insert((VertexType) parents[_]); 194 if (parents[_] == null) 195 return null; 196 _ = parents[_].getId(); 197 } 198 LibraryUtils.setVertexMarks(g, vertexMarksBackup); 199 return ret; 200 } 201 202 /** 203 * returns the parent of v, if ve DFS on parent 204 */ 205 public static <VertexType extends BaseVertex, EdgeType extends BaseEdge<VertexType>> 206 VertexType getParent(BaseGraph<VertexType, EdgeType> g, VertexType treeRoot, VertexType v) { 207 return getPath(g, treeRoot, v).get(1); 208 } 209 210 /** 211 * clears all vertex marks 212 */ 213 public static <VertexType extends BaseVertex, EdgeType extends BaseEdge<VertexType>> 214 void clearVertexMarks(BaseGraph<VertexType, EdgeType> g) { 215 for (VertexType _ : g) { 216 _.setMark(false); 217 } 218 } 219 220 /** 221 * returns the subtree rooted by subTreeRoot in the rooted tree tree with the root treeRoot 222 * the vertices are ordered by their distances to subTreeRoot 223 * the exact distance is placed in v.getProp().obj as an Integer, starting distance is 0 which is subTreeRoot 224 */ 225 public static <Vertex extends BaseVertex, Edge extends BaseEdge<Vertex>> 226 ArrayList<Vertex> getSubTree(BaseGraph<Vertex, Edge> tree, Vertex treeRoot, Vertex subTreeRoot) { 227 boolean vertexMarksBackup[] = LibraryUtils.getVertexMarks(tree); 228 Path<Vertex> pathToRoot = getPath(tree, treeRoot, subTreeRoot); 229 230 clearVertexMarks(tree); 231 232 //close the path to tree root 233 for (Vertex _ : pathToRoot) { 234 _.setMark(true); 235 } 236 ArrayList<Vertex> ret = BFS(tree, subTreeRoot, null); 237 LibraryUtils.setVertexMarks(tree, vertexMarksBackup); 238 239 return ret; 240 241 } 242 243 /** 244 * gets the vertices in the order of AlgorithmUtils.getSubTree() 245 */ 246 public static <Vertex extends BaseVertex, Edge extends BaseEdge<Vertex>> 247 ArrayList<Vertex> BFSOrder(BaseGraph<Vertex, Edge> unRootedTree, Vertex treeRoot) { 248 boolean vertexMarksBackup[] = LibraryUtils.getVertexMarks(unRootedTree); 249 clearVertexMarks(unRootedTree); 250 ArrayList<Vertex> ret = BFS(unRootedTree, treeRoot, null); 251 LibraryUtils.setVertexMarks(unRootedTree, vertexMarksBackup); 252 return ret; 253 } 254 255 /** 256 * runs a BFS on graph, starting the given vertex as the root 257 */ 258 public static <Vertex extends BaseVertex, Edge extends BaseEdge<Vertex>> 259 void BFSrun(BaseGraph<Vertex, Edge> unRootedTree, Vertex treeRoot, BFSListener<Vertex> listener) { 260 boolean vertexMarksBackup[] = LibraryUtils.getVertexMarks(unRootedTree); 261 clearVertexMarks(unRootedTree); 262 BFS(unRootedTree, treeRoot, listener); 263 LibraryUtils.setVertexMarks(unRootedTree, vertexMarksBackup); 264 } 265 266 /** 267 * performs a full BFS on graph, it selects the vertices with minimum degrees as the 268 * roots of the resulting forest 269 * 270 * @param unRootedTree 271 * @param listener 272 * @return 273 */ 274 public static <Vertex extends BaseVertex, Edge extends BaseEdge<Vertex>> 275 void BFS(BaseGraph<Vertex, Edge> unRootedTree, BFSListener<Vertex> listener) { 276 boolean vertexMarksBackup[] = LibraryUtils.getVertexMarks(unRootedTree); 277 clearVertexMarks(unRootedTree); 278 for (Vertex v : unRootedTree) { 279 if (!v.getMark()) { 280 BFS(unRootedTree, v, listener); 281 } 282 } 283 LibraryUtils.setVertexMarks(unRootedTree, vertexMarksBackup); 284 } 285 286 /** 287 * performs a bfs on the given root, 288 * this method changes vertex marks, and also marked vertices will not be traversed 289 * 290 * @param unRootedTree 291 * @param treeRoot 292 * @param listener 293 * @return 294 */ 295 public static <Vertex extends BaseVertex, Edge extends BaseEdge<Vertex>> 296 ArrayList<Vertex> BFS(BaseGraph<Vertex, Edge> unRootedTree, Vertex treeRoot, BFSListener<Vertex> listener) { 297 //do a bfs on the subTreeRoot 298 ArrayList<Vertex> q = new ArrayList<Vertex>(); 299 ArrayList<Vertex> ret = new ArrayList<Vertex>(); 300 q.add(treeRoot); 301 ret.add(treeRoot); 302 treeRoot.setMark(true); 303 treeRoot.getProp().obj = 0; 304 while (!q.isEmpty()) { 305 Vertex v = q.remove(0); 306 for (Vertex _ : getNeighbors(unRootedTree, v)) { 307 if (!_.getMark()) { 308 q.add(_); 309 ret.add(_); 310 _.setMark(true); 311 _.getProp().obj = ((Integer) v.getProp().obj) + 1; //set the distance 312 if (listener != null) 313 listener.visit(_, v); 314 } 315 } 316 } 317 return ret; 318 } 319 320 321 /** 322 * runs a dfs and fills visit and parent, visit is the visiting order of vertices and parent[i] is the id of i'th vertex parent 323 */ 324 public static <VertexType extends BaseVertex, EdgeType extends BaseEdge<VertexType>> 325 void dfs(BaseGraph<VertexType, EdgeType> g, 326 int node, ArrayList visit, int parent[]) { 327 visit.add(node); 328 ArrayList e = getAdjList(g); 329 ArrayList neighbors = (ArrayList) e.get(node); 330 for (Object neighbor1 : neighbors) { 331 int neighbor = (Integer) neighbor1; 332 if (parent[neighbor] == -1) { 333 parent[neighbor] = node; 334 dfs(g, neighbor, visit, parent); 335 } 336 } 337 } 338 339 /** 340 * retunrs the degree of vertex (indegree + outdegree) 341 */ 342 public static int getTotalDegree(BaseGraph g, BaseVertex v) { 343 return g.getOutDegree(v) + g.getInDegree(v); 344 } 345 346 /** 347 * returns the root which is assigned to each vertex 348 * it is the minimum id vertex in the corresponding component of vertex 349 */ 350 public static <Vertex extends BaseVertex, Edge extends BaseEdge<Vertex>> 351 Vertex getRoot(BaseGraph<Vertex, Edge> g, Vertex v) { 352 ArrayList<Vertex> componentVertices = BFSOrder(g, v); 353 Vertex rootCandidate = v; 354 355 for (Vertex _ : componentVertices) { 356 if (_.getId() < v.getId()) { 357 rootCandidate = _; 358 } 359 360 } 361 362 return rootCandidate; 363 364 } 365 366 /** 367 * returns the angle between 3 vertices in graphical world! 368 */ 369 public static double getAngle(VertexModel root, VertexModel v1, VertexModel v2) { 370 371 GraphPoint rootp = root.getLocation(); 372 GraphPoint v1p = v1.getLocation(); 373 GraphPoint v2p = v2.getLocation(); 374 375 return getAngle(rootp, v1p, v2p); 376 } 377 378 /** 379 * returns the angle between 3 points 380 */ 381 public static double getAngle(GraphPoint rootp, GraphPoint v1p, GraphPoint v2p) { 382 double px = v1p.x - rootp.x; 383 double py = v1p.y - rootp.y; 384 double qx = v2p.x - rootp.x; 385 double qy = v2p.y - rootp.y; 386 387 388 double pDOTq = px * qx + py * qy; 389 double plength = getLength(px, py); 390 double qlength = getLength(qx, qy); 391 392 double cartesianProd = py * qx - px * qy; 393 if (plength == 0 || qlength == 0) 394 return 0; 395 else { 396 double alfacos = pDOTq / (plength * qlength); 397 double alfa = Math.acos(alfacos); 398 // return (Math.signum(cartesianProd) < 0 ? 2 * Math.PI - Math.acos(alfacos) : Math.acos(alfacos)); 399 return alfa; 400 } 401 } 402 403 /** 404 * returns the length of the given vector 405 */ 406 public static double getLength(double dx, double dy) { 407 return Point2D.Double.distance(0, 0, dx, dy); 408 } 409 410 /** 411 * moves the vertex relative to its current position 412 */ 413 public static void move(VertexModel v, double dx, double dy) { 414 GraphPoint loc = v.getLocation(); 415 v.setLocation(new GraphPoint(loc.x + dx, loc.y + dy)); 416 } 417 418 /** 419 * returns the distance between two vertices in pixels, (in graphics not the path length between them) 420 */ 421 public static double getDistance(VertexModel v1, VertexModel v2) { 422 return GraphPoint.distance(v1.getLocation().x, v1.getLocation().y, v2.getLocation().x, v2.getLocation().y); 423 424 } 425 426 /** 427 * returns the distance between two points 428 */ 429 public static double getDistance(GraphPoint p1, GraphPoint p2) { 430 return GraphPoint.distance(p1.x, p1.y, p2.x, p2.y); 431 432 } 433 434 /** 435 * @return the angle between vector p2-p1 and X-Axis 436 */ 437 public static double getAngle(GraphPoint p1, GraphPoint p2) { 438 double angle = Math.atan2(p1.y - p2.y, 439 p1.x - p2.x); 440 if (angle < 0) { 441 // atan2 returns getAngle in phase -pi to pi, which means 442 // we have to convert the answer into 0 to 2pi range. 443 angle += 2 * Math.PI; 444 } 445 return angle; 446 } 447 448 /** 449 * locations v in a r-teta cordination 450 */ 451 public static void setLocation(VertexModel v, GraphPoint center, double radius, double ang) { 452 v.setLocation(new GraphPoint(center.x + radius * Math.cos(ang), center.y + radius * Math.sin(ang))); 453 } 454 455 /** 456 * @return the bounding rectangle arround vertices 457 */ 458 public static Rectangle2D.Double getBoundingRegion(Collection<VertexModel> vertices) { 459 Rectangle2D.Double ret = new Rectangle2D.Double(); 460 boolean first = true; 461 for (VertexModel v : vertices) { 462 GraphPoint p = v.getLocation(); 463 if (first) { 464 ret = new Rectangle2D.Double(p.x, p.y, 0, 0); 465 first = false; 466 } 467 ret.add(p); 468 } 469 return ret; 470 } 471 472 public static GraphPoint getCenter(Collection<VertexModel> V) { 473 GraphPoint center = new GraphPoint(0, 0); 474 for (VertexModel v : V) { 475 GraphPoint loc = v.getLocation(); 476 center.x += loc.x; 477 center.y += loc.y; 478 } 479 center.x = center.x / V.size(); 480 center.y = center.y / V.size(); 481 return center; 482 } 483 484 /** 485 * returns the vertex degrees as a list, sorted by vertex ids 486 */ 487 public static <VertexType extends BaseVertex, EdgeType extends BaseEdge<VertexType>> 488 ArrayList<Integer> getDegreesList(BaseGraph<VertexType, EdgeType> g) { 489 ArrayList<Integer> result = new ArrayList<Integer>(); 490 int vCount = g.getVertexArray().length; 491 for (int i = 0; i < vCount; i++) 492 result.add(getDegree(g, i)); 493 return result; 494 } 495 496 public interface BFSListener<Vertex extends BaseVertex> { 497 public void visit(Vertex v, Vertex parent); 498 } 499 500 /** 501 * @param p1 502 * @param p2 503 * @return a point whose x and y are average of the given graph points. 504 */ 505 public static GraphPoint getMiddlePoint(GraphPoint p1, GraphPoint p2) { 506 return new GraphPoint((p1.x + p2.x) / 2, (p1.y + p2.y) / 2); 507 } 508 509 public static GraphPoint normalize(GraphPoint vector) { 510 double size = Math.sqrt(Math.pow(vector.x, 2) + Math.pow(vector.y, 2)); 511 GraphPoint ret = new GraphPoint(vector); 512 if (size != 0) 513 ret.multiply(1 / size); 514 return ret; 515 } 516 }