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 /* 006 * MatrixGraph.java 007 * 008 * Created on November 13, 2004, 8:32 PM 009 * Last Modify on November 15, 2004, 05:03 AM 010 */ 011 012 package graphlab.library; 013 014 015 import Jama.Matrix; 016 import graphlab.library.event.handlers.PreWorkHandler; 017 import graphlab.library.event.handlers.PreWorkPostWorkHandler; 018 import graphlab.library.exceptions.InvalidEdgeException; 019 import graphlab.library.exceptions.InvalidGraphException; 020 import graphlab.library.exceptions.InvalidVertexException; 021 import graphlab.library.genericcloners.EdgeVertexCopier; 022 import graphlab.library.genericcloners.GraphConverter; 023 024 import java.util.ArrayList; 025 import java.util.Iterator; 026 027 028 /** 029 * Adjacency Matrix Graph. 030 * For information about Adjacency Matrix refer to http://en.wikipedia.org/wiki/Adjacency_matrix * @author Omid Aladini 031 * 032 * @author Omid Aladini 033 * @param <VertexType> Type of the vertices the graph can work with. 034 * @param <EdgeType> Type of the edges the graph can work with. 035 */ 036 public class MatrixGraph<VertexType extends BaseVertex, EdgeType extends BaseEdge<VertexType>> 037 extends BaseGraph<VertexType, EdgeType> { 038 /** 039 * The data structure to store graph data, it looks like a three dimensional matrix with EdgeType elements. 040 * The third dimension is designed to store multiple edges between two vertices. 041 * ArrayLists can work with generic type's arameters and they are as fast as arrays for indexing, but 042 * they are not thread safe. So MatrixGraph operations are not thread-safe and should be synchronized 043 * externally. 044 */ 045 private ArrayList<ArrayList<ArrayList<EdgeType>>> adjacencyMatrix; 046 047 //list of vertices 048 private ArrayList<VertexType> vertices; 049 050 //In-degree of vertices by order stored in <code>vertices</code> object. 051 //More clearly, the number of edges which their sources are connected to the vertex. 052 private ArrayList<Integer> inDegree; 053 //Out-degree of vertices by order stored in <code>vertices</code> object. 054 //More clearly, the number of edges which their targets are connected to the vertex. 055 private ArrayList<Integer> outDegree; 056 057 //Specified whether the graph is directed. 058 private boolean directed; 059 private int edgeCount = 0; 060 061 /** 062 * Constructs a graph object that stores graph data using adjacency matrix data structure. 063 * 064 * @param directed Indicated whether the graph is directed. 065 * @param expectedNumberOfVertices Approximate number of vertices that will be 066 * added to the graph. This paramether is optional and is available for performance 067 * reasons. 068 */ 069 public MatrixGraph(boolean directed, int expectedNumberOfVertices) { 070 this.directed = directed; 071 072 adjacencyMatrix = new ArrayList<ArrayList<ArrayList<EdgeType>>>(expectedNumberOfVertices); 073 for (int rowCount = 0; rowCount < expectedNumberOfVertices; rowCount++) { 074 ArrayList<ArrayList<EdgeType>> columns = new ArrayList<ArrayList<EdgeType>>(expectedNumberOfVertices); 075 adjacencyMatrix.add(columns); 076 } 077 vertices = new ArrayList<VertexType>(expectedNumberOfVertices); 078 079 inDegree = new ArrayList<Integer>(expectedNumberOfVertices); 080 081 if (!directed) 082 outDegree = inDegree; 083 else 084 outDegree = new ArrayList<Integer>(expectedNumberOfVertices); 085 } 086 087 /** 088 * Constructs a MatrixGraph object 089 * 090 * @param directed Whether the graph is directed or undirected. 091 */ 092 public MatrixGraph(boolean directed) { 093 this(directed, 5); 094 } 095 096 /** 097 * Constructs an undirected graph object that stores graph data using 098 * adjacency list data structure. 099 */ 100 public MatrixGraph() { 101 this(false, 5); 102 } 103 104 /** 105 * Constructs a graph object that stores graph data using adjacency matrix data structure by importing 106 * graph data from a pre-existing graph. A GraphConvertor object is passed as a parameter which is 107 * reponsible for duplication/type-convertion of graph elements. 108 * 109 * @param <ImportVertexType> The type of vertex object which the input graph contain. 110 * @param <ImportEdgeType> The type of edge object which the input graph contain. 111 * @param graph 112 * @param converter A GraphConverter object which is responsible for duplicating/converting graph 113 * elements. 114 * @throws InvalidGraphException Throws when the input graph is an invalid graph object. 115 */ 116 public <ImportVertexType extends BaseVertex, 117 ImportEdgeType extends BaseEdge<ImportVertexType>, 118 ImportGraphType extends BaseGraph<ImportVertexType, ImportEdgeType> 119 > 120 MatrixGraph(BaseGraph<ImportVertexType, ImportEdgeType> graph, 121 GraphConverter<ImportVertexType, 122 VertexType, 123 ImportEdgeType, 124 EdgeType, 125 ImportGraphType, 126 MatrixGraph<VertexType, EdgeType>> gc) 127 throws InvalidGraphException { 128 ArrayList<VertexType> tempAL = new ArrayList<VertexType>(getVerticesCount()); 129 130 for (ImportVertexType v : graph) { 131 insertVertex(gc.convert(v)); 132 tempAL.add(gc.convert(v)); 133 } 134 135 Iterator<ImportEdgeType> iet = graph.edgeIterator(); 136 137 ImportEdgeType edge; 138 try { 139 while (iet.hasNext()) { 140 edge = iet.next(); 141 insertEdge(gc.convert(edge, tempAL.get(edge.source.getId()), tempAL.get(edge.target.getId()))); 142 } 143 } catch (InvalidVertexException e) { 144 throw new InvalidGraphException(); 145 } 146 } 147 148 /* (non-Javadoc) 149 * @see graphlab.library.BaseGraph#getVerticesCount() 150 */ 151 @Override 152 public int getVerticesCount() { 153 return vertices.size(); 154 } 155 156 /** 157 * Checks if a vertex with internal id <i>id</i> exist. 158 * 159 * @param id Id of the vertex. 160 * @return true of exist false if not. 161 */ 162 private boolean vertexIdOutOfRange(int id) { 163 return id < 0 || id >= vertices.size(); 164 165 } 166 167 /** 168 * Returns the vertex with internal id <I>id</I> 169 * 170 * @param id Internal index of the vertex. 171 * @return Reference of the vertex object. 172 */ 173 private VertexType getVertex(int id) 174 throws InvalidVertexException { 175 if (vertexIdOutOfRange(id)) 176 throw new InvalidVertexException(); 177 178 return vertices.get(id); 179 } 180 181 /** 182 * Lables the vertices using their internal Id property by the index they live inside the graph. 183 */ 184 private void setVertexIds() { 185 try { 186 for (int i = 0; i < getVerticesCount(); i++) 187 getVertex(i).setId(i); 188 } catch (InvalidVertexException e) { 189 System.out.println("NEVER-HAPPENS EXCEPTION"); 190 e.printStackTrace(); 191 } 192 } 193 194 195 /* (non-Javadoc) 196 * @see graphlab.library.BaseGraph#insertEdge(null) 197 */ 198 @Override 199 public void insertEdge(EdgeType newEdge) 200 throws InvalidVertexException { 201 VertexType sourceObj, targetObj; 202 int source, target; 203 204 sourceObj = newEdge.source; 205 targetObj = newEdge.target; 206 source = newEdge.source.getId(); 207 target = newEdge.target.getId(); 208 209 checkVertex(sourceObj); 210 checkVertex(targetObj); 211 212 ArrayList<EdgeType> edges; 213 214 if (adjacencyMatrix.get(source).get(target) == null) { 215 edges = new ArrayList<EdgeType>(5); 216 adjacencyMatrix.get(source).set(target, edges); 217 } else { 218 edges = adjacencyMatrix.get(source).get(target); 219 } 220 221 edges.add(newEdge); 222 223 if (!directed) 224 adjacencyMatrix.get(target).set(source, edges); 225 226 outDegree.set(source, inDegree.get(source) + 1); 227 inDegree.set(target, inDegree.get(target) + 1); 228 229 if (!directed) { 230 inDegree.set(source, inDegree.get(source) + 1); 231 outDegree.set(target, inDegree.get(target) + 1); 232 } 233 234 ++edgeCount; 235 236 } 237 238 /** 239 * Returns all edges between two vertices. 240 * 241 * @param source Index of the edges' start point. 242 * @param target Index of the edges' end point. 243 * @return An ArrayList of <I>EdgeType</I> containing all edges between <I>from</I> and <I>to</I>. 244 * @throws graphlab.library.exceptions.InvalidVertexException 245 * Thrown when two supplied indexes of vertices are invalid. 246 */ 247 private ArrayList<EdgeType> getEdges(int source, int target) 248 throws InvalidVertexException { 249 if (vertexIdOutOfRange(source) || vertexIdOutOfRange(target)) 250 throw new InvalidVertexException(); 251 252 return adjacencyMatrix.get(source).get(target); 253 } 254 255 /** 256 * Returns all edges between two vertices. 257 * 258 * @param from Index of the edges' start point. 259 * @param to Index of the edges' end point. 260 * @return An ArrayList of <I>EdgeType</I> containing all edges between <I>from</I> and <I>to</I>. 261 * @throws graphlab.library.exceptions.InvalidVertexException 262 * Thrown when two supplied indexes of vertices are invalid. 263 */ 264 @Override 265 public ArrayList<EdgeType> getEdges(VertexType source, VertexType target) 266 throws InvalidVertexException { 267 int sourceId = source.getId(); 268 int targetId = target.getId(); 269 270 checkVertex(target); 271 checkVertex(source); 272 273 return adjacencyMatrix.get(sourceId).get(targetId); 274 } 275 276 /* (non-Javadoc) 277 * @see graphlab.library.BaseGraph#insertVertex(null) 278 */ 279 @Override 280 public void insertVertex(VertexType newVertex) { 281 vertices.add(newVertex); 282 int size = getVerticesCount(); 283 newVertex.setId(size - 1); 284 285 if (adjacencyMatrix.size() < size) { 286 adjacencyMatrix.ensureCapacity(size * 2); 287 adjacencyMatrix.add(new ArrayList<ArrayList<EdgeType>>()); 288 } 289 290 int newSize = adjacencyMatrix.size(); 291 for (int row = 0; row < newSize; row++) { 292 if (row == newSize - 1) { 293 for (int newSizeIndex = 0; newSizeIndex < newSize; newSizeIndex++) { 294 adjacencyMatrix.get(row).add(null); 295 } 296 } else { 297 adjacencyMatrix.get(row).add(null); 298 } 299 } 300 301 inDegree.add(0); 302 outDegree.add(0); 303 304 } 305 306 /** 307 * Runs Depth First Search (DFS) algorithm on the graph starting from vertex <I>vertexId</I>. 308 * A reference to a PreWorkPostWorkHandler is supplied that contains implementation 309 * of pre-work and post-work operations that depends on the application of DFS. 310 * 311 * @param vertex Starting vertex of the traversal. 312 * @param handler A reference to a PreWorkPostWorkHandler that contains implementation 313 * of pre-work and post-work operations that depends on the application of DFS. 314 * @return Whether the traversal has stopped at the middle by the handler. 315 * @throws InvalidVertexException 316 */ 317 318 public boolean depthFirstSearch(VertexType vertex, PreWorkPostWorkHandler<VertexType> handler) throws InvalidVertexException { 319 return new graphlab.library.algorithms.traversal.DepthFirstSearch<VertexType, EdgeType>(this) 320 .doSearch(vertex, handler); 321 } 322 323 324 /** 325 * Runs Breadth First Search (BFS) algorithm on the graph starting from vertex <I>vertexId</I>. 326 * A reference to a PreWorkHandler is supplied that contains implementation 327 * of pre-work operation that depends on the application of BFS. 328 * 329 * @param vertex Starting vertex of the traversal. 330 * @param handler A reference to a PreWorkHandler that contains implementation 331 * of pre-work operation that depends on the application of DFS. 332 * @return Whether the traversal has stopped at the middle by the handler. 333 * @throws InvalidVertexException 334 */ 335 public boolean breadthFirstSearch(VertexType vertex, PreWorkHandler<VertexType> handler) throws InvalidVertexException { 336 return new graphlab.library.algorithms.traversal.BreadthFirstSearch<VertexType, EdgeType>(this) 337 .doSearch(vertex, handler); 338 339 } 340 341 /** 342 * Checks whether the current graph is a connected graph. 343 * 344 * @return True if graph is connected and false otherwise. 345 */ 346 public boolean isGraphConnected() { 347 try { 348 return graphlab.library.algorithms.util.ConnectivityChecker.isGraphConnected(this); 349 350 } catch (InvalidGraphException e) { 351 //Generally should not happen. So I don't bother the user by 352 //adding throws declaration. 353 e.printStackTrace(); 354 return false; 355 } 356 } 357 358 /** 359 * Checks whether the current graph is acyclic. 360 * 361 * @return True if graph is acyclic and false otherwise. 362 */ 363 public boolean isGraphAcyclic() { 364 try { 365 //Soooo easy to use! 366 return graphlab.library.algorithms.util.AcyclicChecker.isGraphAcyclic(this); 367 } catch (InvalidGraphException e) { 368 //Generally should not happen. So I don't bother the user by 369 //adding throws declaration. 370 e.printStackTrace(); 371 return false; 372 } 373 } 374 375 /* (non-Javadoc) 376 * @see java.lang.Iterable#iterator() 377 */ 378 @Override 379 public Iterator<VertexType> iterator() { 380 return vertices.iterator(); 381 } 382 383 /* (non-Javadoc) 384 * @see graphlab.library.BaseGraph#isDirected() 385 */ 386 @Override 387 public boolean isDirected() { 388 return directed; 389 } 390 391 /** 392 * Returns in-degree of vertex <I>vertexId</I>, the number of edges which 393 * their target goes to the specified vertex. 394 * 395 * @return in-degree of vertex <I>vertexId</I>. 396 * @throws InvalidVertexException 397 */ 398 private int getInDegree(int vertexId) throws InvalidVertexException { 399 if (vertexIdOutOfRange(vertexId)) 400 throw new InvalidVertexException(); 401 return inDegree.get(vertexId); 402 } 403 404 /** 405 * Returns out-degree of vertex <I>vertexId</I>, the number of edges which 406 * their tale is attached to the specified vertex. 407 * 408 * @return out-degree of vertex <I>vertexId</I>. 409 * @throws InvalidVertexException 410 */ 411 private int getOutDegree(int vertexId) throws InvalidVertexException { 412 if (vertexIdOutOfRange(vertexId)) 413 throw new InvalidVertexException(); 414 return outDegree.get(vertexId); 415 } 416 417 /** 418 * This class iterates all, edges coming from or going to a specified vertex. 419 * The order of edges the iterator iterate is undefined because of future code changes. 420 * 421 * @author Omid Aladini 422 */ 423 private class EdgeIterator implements Iterator<EdgeType> { 424 private Iterator<EdgeType> edgesIterator; 425 private EdgeType lastEdge = null; 426 427 /** 428 * Constructs an Edge Iterator object which iterates through all the edges in the graph. 429 * Note that if the graph object is changed during iteration, the iteration may not 430 * actually represent current state of the graph. For example, if you deleted an edge 431 * after construction of this object, the edge would be included in the iteration. 432 */ 433 public EdgeIterator() { 434 ArrayList<EdgeType> edges = new ArrayList<EdgeType>(); 435 if (directed) { 436 for (ArrayList<ArrayList<EdgeType>> aae : adjacencyMatrix) 437 for (ArrayList<EdgeType> ae : aae) 438 for (EdgeType e : ae) 439 edges.add(e); 440 } else { 441 int iCount = 0; 442 int jCount; 443 for (ArrayList<ArrayList<EdgeType>> aae : adjacencyMatrix) { 444 Iterator<ArrayList<EdgeType>> it = aae.iterator(); 445 jCount = 0; 446 while (iCount >= jCount) { 447 ++jCount; 448 449 ArrayList<EdgeType> ae = it.next(); 450 451 if (ae == null) 452 continue; 453 454 for (EdgeType e : ae) 455 edges.add(e); 456 } 457 ++iCount; 458 } 459 } 460 edgesIterator = edges.iterator(); 461 } 462 463 464 /** 465 * Number of times edge Iteration is called. This will set as a temporary flag into 466 * edges in order to reduce running time of edge iteration back to O(n^2). 467 */ 468 int edgeIterationIndex = 0; 469 470 /** 471 * Constructs an Edge Iterator object which iterates through all the edges going to 472 * or coming from the specified vertex <code>v</code>. 473 * Note that if the graph object is changed during iteration, the iteration may not 474 * actually represent current state of the graph. For example, if you deleted an edge 475 * after construction of this object, the edge would be included in the iteration. 476 * 477 * @param v Source or target of desired edges. 478 */ 479 private EdgeIterator(VertexType v) 480 throws InvalidVertexException { 481 checkVertex(v); 482 483 if (!directed) 484 ++edgeIterationIndex; 485 486 ArrayList<EdgeType> edges = new ArrayList<EdgeType>(); 487 488 ArrayList<ArrayList<EdgeType>> row = adjacencyMatrix.get(v.getId()); 489 490 for (ArrayList<EdgeType> ae : row) 491 for (EdgeType e : ae) { 492 edges.add(e); 493 494 if (!directed) 495 e.edgeIterationIndex = edgeIterationIndex; 496 } 497 498 for (ArrayList<ArrayList<EdgeType>> aae : adjacencyMatrix) { 499 if (row == aae) 500 continue; 501 for (ArrayList<EdgeType> ae : aae) 502 for (EdgeType e : ae) { 503 if (e.target == v) { 504 if (directed) { 505 edges.add(e); 506 } else if (e.edgeIterationIndex != edgeIterationIndex) { 507 e.edgeIterationIndex = edgeIterationIndex; 508 edges.add(e); 509 } 510 } 511 } 512 } 513 514 edgesIterator = edges.iterator(); 515 } 516 517 /** 518 * Constructs an Edge Iterator object which iterates through all the edges going to 519 * or coming from (depending on the second parameter) the specified vertex <code>v</code>. 520 * If the second parameter it true, then the first parameter is considered to be source of 521 * all desired edges, and if it's false the first parameter is considered to be target of desired edges. 522 * Note that if the graph object is changed during iteration, the iteration may not 523 * actually represent current state of the graph. For example, if you deleted an edge 524 * after construction of this object, the edge would be included in the iteration. 525 * 526 * @param v If the second parameter is true indicated the vertex which is source of desired edges, otherwise 527 * it is considered to be target of desired edges. 528 * @param source True means the first parameter should be considered source of desired edges. 529 */ 530 public EdgeIterator(VertexType v, boolean source) 531 throws InvalidVertexException { 532 checkVertex(v); 533 534 if (!directed) 535 ++edgeIterationIndex; 536 537 ArrayList<EdgeType> edges = new ArrayList<EdgeType>(); 538 539 ArrayList<ArrayList<EdgeType>> row = adjacencyMatrix.get(v.getId()); 540 541 if (source) { 542 for (ArrayList<EdgeType> ae : row) 543 for (EdgeType e : ae) { 544 edges.add(e); 545 if (!directed) 546 e.edgeIterationIndex = edgeIterationIndex; 547 } 548 } else { 549 for (ArrayList<ArrayList<EdgeType>> aae : adjacencyMatrix) { 550 if (row == aae) 551 continue; 552 for (ArrayList<EdgeType> ae : aae) 553 for (EdgeType e : ae) { 554 if (e.target == v) { 555 if (directed) { 556 edges.add(e); 557 } else if (e.edgeIterationIndex != edgeIterationIndex) { 558 e.edgeIterationIndex = edgeIterationIndex; 559 edges.add(e); 560 } 561 } 562 } 563 } 564 } 565 edgesIterator = edges.iterator(); 566 567 } 568 569 public boolean hasNext() { 570 return edgesIterator.hasNext(); 571 } 572 573 public EdgeType next() { 574 lastEdge = edgesIterator.next(); 575 return lastEdge; 576 } 577 578 public void remove() { 579 try { 580 removeEdge(lastEdge); 581 } catch (InvalidEdgeException e) { 582 System.out.println("Invalid remove operation."); 583 e.printStackTrace(); 584 } 585 } 586 587 } 588 589 /** 590 * Returns iterator object for the edges. 591 * 592 * @return iterator object for the edges. 593 */ 594 public Iterator<EdgeType> edgeIterator() { 595 return new EdgeIterator(); 596 597 } 598 599 public Iterable<EdgeType> edges() { 600 return new Iterable<EdgeType>() { 601 public Iterator<EdgeType> iterator() { 602 return edgeIterator(); 603 } 604 }; 605 } 606 607 /* (non-Javadoc) 608 * @see graphlab.library.BaseGraph#edgeIterator(null) 609 */ 610 @Override 611 public Iterator<EdgeType> edgeIterator(VertexType v) 612 throws InvalidVertexException { 613 return new EdgeIterator(v); 614 } 615 616 /* (non-Javadoc) 617 * @see graphlab.library.BaseGraph#getAdjacencyMatrix() 618 */ 619 @Override 620 public Matrix getAdjacencyMatrix() { 621 Matrix matrix = new Matrix(getVerticesCount(), getVerticesCount()); 622 try { 623 if (directed) { 624 for (int i = 0; i < getVerticesCount(); i++) 625 for (int j = 0; j < getVerticesCount(); j++) 626 if (getEdges(i, j) != null) 627 matrix.set(i, j, getEdges(i, j).size()); 628 } else { 629 for (int i = 0; i < getVerticesCount(); i++) 630 for (int j = 0; j <= i; j++) 631 if (getEdges(i, j) != null) { 632 matrix.set(i, j, getEdges(i, j).size()); 633 if (i != j) 634 matrix.set(j, i, getEdges(i, j).size()); 635 } 636 } 637 } catch (Exception e) { 638 //never happens 639 System.out.println("NEVER-HAPPENS-BUG:getAdjMatrix:"); 640 e.printStackTrace(); 641 } 642 return matrix; 643 } 644 645 /* (non-Javadoc) 646 * @see graphlab.library.BaseGraph#dump() 647 */ 648 @Override 649 public void dump() { 650 System.out.print('\n'); 651 for (int i = 0; i < getVerticesCount(); i++) { 652 for (int j = 0; j < getVerticesCount(); j++) { 653 System.out.print(" "); 654 System.out.print(adjacencyMatrix.get(i).get(j) == null ? 0 : 1); 655 } 656 System.out.println(""); 657 } 658 } 659 660 /* (non-Javadoc) 661 * @see graphlab.library.BaseGraph#removeAllEdges(null, null) 662 */ 663 @Override 664 public void removeAllEdges(VertexType source, VertexType target) throws InvalidVertexException { 665 if (vertexIdOutOfRange(source.getId()) || vertexIdOutOfRange(target.getId()) || 666 source != vertices.get(source.getId()) || target != vertices.get(target.getId())) 667 throw new InvalidVertexException(); 668 669 adjacencyMatrix.get(source.getId()).get(target.getId()).clear(); 670 671 if (!directed) 672 removeAllEdges(target, source); 673 } 674 675 /** 676 * Removes a vertex and all it's connected edges. 677 * 678 * @param vertexId index of the vertex to be removed 679 */ 680 private void removeVertex(int vertexId) 681 throws InvalidVertexException { 682 for (ArrayList<ArrayList<EdgeType>> c : adjacencyMatrix) { 683 c.remove(vertexId); 684 } 685 adjacencyMatrix.remove(vertexId); 686 687 vertices.remove(vertexId); 688 inDegree.remove(vertexId); 689 outDegree.remove(vertexId); 690 691 setVertexIds(); 692 } 693 694 /* (non-Javadoc) 695 * @see graphlab.library.BaseGraph#removeVertex(null) 696 */ 697 @Override 698 public void removeVertex(VertexType v) throws InvalidVertexException { 699 checkVertex(v); 700 removeVertex(v.getId()); 701 } 702 703 /* (non-Javadoc) 704 * @see graphlab.library.BaseGraph#getInDegree(null) 705 */ 706 @Override 707 public int getInDegree(VertexType v) throws InvalidVertexException { 708 checkVertex(v); 709 return getInDegree(v.getId()); 710 } 711 712 /* (non-Javadoc) 713 * @see graphlab.library.BaseGraph#getOutDegree(null) 714 */ 715 @Override 716 public int getOutDegree(VertexType v) throws InvalidVertexException { 717 checkVertex(v); 718 return getOutDegree(v.getId()); 719 } 720 721 /* (non-Javadoc) 722 * @see graphlab.library.BaseGraph#removeEdge(null) 723 */ 724 @Override 725 public void removeEdge(EdgeType edge) 726 throws InvalidEdgeException { 727 int source = edge.source.getId(); 728 int target = edge.target.getId(); 729 730 try { 731 checkVertex(edge.target); 732 checkVertex(edge.source); 733 } catch (InvalidVertexException e) { 734 throw new InvalidEdgeException(); 735 } 736 737 adjacencyMatrix.get(target).get(source).remove(edge); 738 739 if (!directed) 740 adjacencyMatrix.get(source).get(target).remove(edge); 741 742 --edgeCount; 743 } 744 745 public VertexType getAVertex() { 746 Iterator<VertexType> it = iterator(); 747 if (it.hasNext()) 748 return it.next(); 749 else 750 return null; 751 } 752 753 /* (non-Javadoc) 754 * @see graphlab.library.BaseGraph#copy(graphlab.library.GraphConverter) 755 */ 756 @Override 757 public BaseGraph<VertexType, EdgeType> 758 copy(EdgeVertexCopier<VertexType, EdgeType> gc) 759 throws InvalidGraphException { 760 MatrixGraph<VertexType, EdgeType> oGraph = new MatrixGraph<VertexType, EdgeType>(directed, getVerticesCount()); 761 762 ArrayList<VertexType> tempAL = new ArrayList<VertexType>(getVerticesCount()); 763 764 VertexType tempVertex; 765 for (VertexType v : this) { 766 tempVertex = gc.convert(v); 767 oGraph.insertVertex(tempVertex); 768 tempAL.add(tempVertex); 769 } 770 771 Iterator<EdgeType> iet = edgeIterator(); 772 773 EdgeType edge; 774 try { 775 while (iet.hasNext()) { 776 edge = iet.next(); 777 oGraph.insertEdge(gc.convert(edge, tempAL.get(edge.source.getId()), tempAL.get(edge.target.getId()))); 778 } 779 } catch (InvalidVertexException e) { 780 throw new InvalidGraphException(); 781 782 } 783 784 return oGraph; 785 } 786 787 /* (non-Javadoc) 788 * @see graphlab.library.BaseGraph#containsVertex(null) 789 */ 790 @Override 791 public boolean containsVertex(VertexType v) { 792 return vertices.contains(v); 793 } 794 795 /* (non-Javadoc) 796 * @see graphlab.library.BaseGraph#checkVertex(null) 797 */ 798 @Override 799 public void checkVertex(VertexType v) 800 throws InvalidVertexException { 801 if (vertexIdOutOfRange(v.getId()) || v != vertices.get(v.getId())) 802 throw new InvalidVertexException(); 803 } 804 805 @Override 806 public boolean isEdge(VertexType source, VertexType target) 807 throws InvalidVertexException { 808 return (getEdges(source, target) != null) && (getEdges(source, target).size() != 0); 809 } 810 811 @Override 812 public MatrixGraph<VertexType, EdgeType> createEmptyGraph() { 813 return new MatrixGraph<VertexType, EdgeType>(directed, 0); 814 } 815 816 @Override 817 public void setDirected(boolean isDirected) { 818 //TODO: Stub 819 throw new RuntimeException("Not yet implemented."); 820 } 821 822 /* (non-Javadoc) 823 * @see graphlab.library.BaseGraph#getVertexArray() 824 */ 825 @Override 826 public BaseVertex[] getVertexArray() { 827 BaseVertex[] arr = new BaseVertex[getVerticesCount()]; 828 829 for (VertexType v : this) 830 arr[v.getId()] = v; 831 832 return arr; 833 } 834 835 /* (non-Javadoc) 836 * @see graphlab.library.BaseGraph#getEdgeArray() 837 */ 838 @Override 839 public int[][] getEdgeArray() { 840 int[][] arr = new int[getVerticesCount()][]; 841 842 int i = 0; 843 int j; 844 int k; 845 846 for (ArrayList<ArrayList<EdgeType>> ll : adjacencyMatrix) { 847 j = 0; 848 849 ArrayList<Integer> temp = new ArrayList<Integer>(); 850 851 for (ArrayList<EdgeType> alet : ll) { 852 if (alet != null && alet.size() != 0) 853 temp.add(j++); 854 } 855 856 arr[i] = new int[temp.size()]; 857 858 k = 0; 859 for (Integer vertexId : temp) 860 arr[i][k++] = vertexId; 861 862 ++i; 863 } 864 return arr; 865 } 866 867 /* (non-Javadoc) 868 * @see graphlab.library.BaseGraph#lightEdgeIterator() 869 */ 870 @Override 871 public Iterator<EdgeType> lightEdgeIterator() { 872 //TODO: Stub, not yet light. 873 return edgeIterator(); 874 } 875 876 /* (non-Javadoc) 877 * @see graphlab.library.BaseGraph#lightEdgeIterator(null) 878 */ 879 @Override 880 public Iterator<EdgeType> lightEdgeIterator(VertexType v) throws InvalidVertexException { 881 //TODO: Stub, not yet light. 882 return edgeIterator(v); 883 } 884 885 /* (non-Javadoc) 886 * @see graphlab.library.BaseGraph#clear() 887 */ 888 @Override 889 public void clear() { 890 int expectedNumberOfVertices = 0; 891 adjacencyMatrix = new ArrayList<ArrayList<ArrayList<EdgeType>>>(expectedNumberOfVertices); 892 for (int rowCount = 0; rowCount < expectedNumberOfVertices; rowCount++) { 893 ArrayList<ArrayList<EdgeType>> columns = new ArrayList<ArrayList<EdgeType>>(expectedNumberOfVertices); 894 adjacencyMatrix.add(columns); 895 } 896 vertices = new ArrayList<VertexType>(expectedNumberOfVertices); 897 898 inDegree = new ArrayList<Integer>(expectedNumberOfVertices); 899 900 if (!directed) 901 outDegree = inDegree; 902 else 903 outDegree = new ArrayList<Integer>(expectedNumberOfVertices); 904 905 edgeCount = 0; 906 } 907 908 @Override 909 public int getEdgesCount() { 910 return edgeCount; 911 } 912 } 913