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