001    // GraphLab Project: http://graphlab.sharif.edu
002    // Copyright (C) 2008 Mathematical Science Department of Sharif University of Technology
003    // Distributed under the terms of the GNU Lesser General Public License (LGPL): http://www.gnu.org/licenses/
004    
005    package graphlab.library.algorithms.shortestpath;
006    
007    import graphlab.library.BaseEdge;
008    import graphlab.library.BaseGraph;
009    import graphlab.library.BaseVertex;
010    import graphlab.library.algorithms.Algorithm;
011    import graphlab.library.algorithms.AutomatedAlgorithm;
012    import graphlab.library.algorithms.util.EventUtils;
013    import graphlab.library.event.GraphRequest;
014    import graphlab.library.event.VertexEvent;
015    import graphlab.library.event.VertexRequest;
016    import graphlab.library.exceptions.InvalidVertexException;
017    
018    import java.util.*;
019    
020    
021    /**
022     * This method finds the shortest path from a vertex to all vertices
023     * of a graph.
024     * [Should be tested]
025     *
026     * @author Omid Aladini
027     */
028    public class Dijkstra<VertexType extends BaseVertex,
029            EdgeType extends BaseEdge<VertexType>> extends Algorithm
030            implements AutomatedAlgorithm {
031        /**
032         * This method finds a reference array using Dijkstra algorithm
033         * from which, one can find
034         * the shortest paths of all vertices of a graph from an arbitrary
035         * given vertex.
036         *
037         * @param graph  Graph object to be searched.
038         * @param vertex The source of the paths.
039         * @return Vector of vertices that for each i, it has a reference to
040         *         the vertex, before the vertex with ID number i in the shortest path
041         *         from "vertex" to i, or null if there is no such vertex.
042         * @throws InvalidVertexException if the supplied vertices are invalid.
043         */
044        public Vector<VertexType>
045        getShortestPath(final BaseGraph<VertexType, EdgeType> graph,
046                        VertexType vertex)
047                throws InvalidVertexException {
048            graph.checkVertex(vertex);
049    
050            final Integer dist[] = new Integer[graph.getVerticesCount()];
051            //the edge connected to i'th vertex
052            final HashMap<VertexType, EdgeType> edges = new HashMap<VertexType, EdgeType>();
053            Vector<VertexType> prev = new Vector<VertexType>();
054    
055            for (int i = 0; i < dist.length; i++)
056                dist[i] = Integer.MAX_VALUE;
057    
058            dist[vertex.getId()] = 0;
059    
060            class VertexComparator implements Comparator<VertexType> {
061                public int compare(VertexType o1, VertexType o2) {
062                    if (dist[o1.getId()] < dist[o2.getId()])
063                        return -1;
064                    if (dist[o1.getId()] == dist[o2.getId()])
065                        return 0;
066                    else
067                        return 1;
068                }
069            }
070    
071            VertexComparator vComp = new VertexComparator();
072    
073            //selected vertices
074            HashSet<VertexType> selectedVertices = new HashSet<VertexType>();
075    
076            PriorityQueue<VertexType> Q = new PriorityQueue<VertexType>(1, vComp);
077    
078            Q.add(vertex);
079            dispatchEvent(new VertexEvent<VertexType, EdgeType>(graph, vertex, VertexEvent.EventType.MARK));
080            vertex.setMark(true);
081            while (!Q.isEmpty()) {
082                VertexType vMin = Q.poll();
083                vMin.setMark(true);
084                EdgeType edg = edges.get(vMin);
085                if (edg != null)
086                    edg.setMark(true);
087    //            vMin.setColor(2);
088                EventUtils.algorithmStep(this, "");
089                selectedVertices.add(vMin);
090                Iterator<EdgeType> iet = graph.edgeIterator(vMin);
091                while ((iet.hasNext())) {
092                    EdgeType edge = iet.next();
093    //                edge.setColor((int) (Math.random() * 10));
094    //           EventUtils.algorithmStep(this,600);
095                    VertexType target = vMin == edge.source ? edge.target : edge.source;
096                    VertexType source = vMin;
097                    if (!selectedVertices.contains(target)) {
098                        if (dist[target.getId()] > dist[source.getId()] + edge.getWeight()) {
099                            dist[target.getId()] = dist[source.getId()] + edge.getWeight();
100    //                        dispatchEvent(new EdgeEvent<VertexType, EdgeType>(graph, edge, EdgeEvent.EventType.MARK));
101    //                        dispatchEvent(new VertexEvent<VertexType, EdgeType>(graph, target, VertexEvent.EventType.MARK));
102    //                        edge.setMark(true);
103                            edges.put(target, edge);
104    //                        target.setMark(true);
105    //                        target.setColor(5);
106                            Q.add(target);
107    //                        prev.add(edge.source.getId(), edge.target);
108                        }
109                    }
110                }
111            }
112    
113            return prev;
114        }
115    
116        public void doAlgorithm() {
117            GraphRequest<VertexType, EdgeType> gr = new GraphRequest<VertexType, EdgeType>();
118            dispatchEvent(gr);
119            BaseGraph<VertexType, EdgeType> g = gr.getGraph();
120            VertexRequest<VertexType, EdgeType> vr = new VertexRequest<VertexType, EdgeType>(g, "Please choose a vertex for the Dijkstra algorithm.");
121            dispatchEvent(vr);
122            VertexType v = vr.getVertex();
123            getShortestPath(g, v);
124        }
125    }