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.event.GraphRequest; 013 import graphlab.library.event.VertexRequest; 014 015 import java.util.Iterator; 016 import java.util.Vector; 017 018 /** 019 * This method finds the shortest path from a source vertex v, to all 020 * vertices of the graph. 021 * Unlike dijkstra, this method will works properly, for 022 * graphs with negative edges, as well as graphs with non negative edge's 023 * weights. 024 * 025 * @author Soroush Sabet 026 */ 027 public class BellmanFord<VertexType extends BaseVertex, EdgeType extends BaseEdge<VertexType>> extends Algorithm implements AutomatedAlgorithm { 028 private BaseGraph<VertexType, EdgeType> graph; 029 030 /** 031 * A graph with a negative cycle is not well defined 032 * as the input of a shortest path algorithm. Bellman-Ford 033 * algorithms checks for this inconvenienc, along with 034 * solving the single source shortest path algorithm. 035 * 036 * @param graph with arbitrary edge weights. 037 * @param Vertex as the source. 038 * @return null if there be a negative cycle in the graph; 039 * and the vector of predecessors, otherwise. 040 */ 041 042 public Vector<VertexType> computePaths 043 (final BaseGraph<VertexType, EdgeType> graph, VertexType Vertex) { 044 045 // graph.checkVertex(Vertex); 046 047 Integer[] dist; 048 dist = new Integer[graph.getVerticesCount()]; 049 Vector<VertexType> ret = new Vector<VertexType>(); 050 051 for (int i = 0; i < dist.length; i++) 052 dist[i] = Integer.MAX_VALUE; 053 054 dist[Vertex.getId()] = 0; 055 056 EdgeType edge; 057 int i; 058 Iterator<EdgeType> iet; 059 060 for (i = 1; i < graph.getVerticesCount(); i++) { 061 iet = graph.edgeIterator(); 062 while (iet.hasNext()) { 063 edge = iet.next(); 064 if (dist[edge.source.getId()] > dist[edge.target.getId()] + edge.getWeight()) { 065 dist[edge.source.getId()] = dist[edge.target.getId()] + edge.getWeight(); 066 ret.add(edge.source.getId(), edge.target); 067 } 068 } 069 } 070 071 iet = graph.edgeIterator(); 072 while (iet.hasNext()) { 073 edge = iet.next(); 074 if (dist[edge.source.getId()] > dist[edge.target.getId()] + edge.getWeight()) 075 return null; 076 } 077 return ret; 078 } 079 080 public void doAlgorithm() { 081 GraphRequest<VertexType, EdgeType> gr = new GraphRequest<VertexType, EdgeType>(); 082 dispatchEvent(gr); 083 this.graph = gr.getGraph(); 084 VertexRequest<VertexType, EdgeType> vr = new VertexRequest<VertexType, EdgeType>(graph, "Please choose a vertex for the BellmanFord algorithm."); 085 dispatchEvent(vr); 086 Vector<VertexType> vv = this.computePaths(graph, vr.getVertex()); 087 for (VertexType v : vv) 088 v.setColor(v.getColor() + 1); 089 //how to show the results?? 090 } 091 }