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    }