// GraphTea Project: http://github.com/graphtheorysoftware/GraphTea
// Copyright (C) 2012 Graph Theory Software Foundation: http://GraphTheorySoftware.com
// Copyright (C) 2008 Mathematical Science Department of Sharif University of Technology
// Distributed under the terms of the GNU Lesser General Public License (LGPL): http://www.gnu.org/licenses/
package graphtea.library.algorithms.shortestpath;
import graphtea.library.BaseEdge;
import graphtea.library.BaseGraph;
import graphtea.library.BaseVertex;
import graphtea.library.algorithms.Algorithm;
import graphtea.library.genericcloners.BaseEdgeVertexCopier;
import java.util.Collection;
import java.util.Iterator;
import java.util.Vector;
/**
* This Algorithm computes the lenght of the shortest
* path between any two arbitrary vertices.
* This method is usually used for sparse graphs.
*
* @author Soroush Sabet
*/
public class Johnson
<VertexType extends BaseVertex, EdgeType extends BaseEdge<VertexType>, GraphType extends BaseGraph<VertexType, EdgeType>>
extends Algorithm {
int[] a;
int[][] d;
//HashMap nw = new HashMap<EdgeType,Integer>();
Johnson() {
}
public int[][] ComputePaths(GraphType g) {
BaseEdgeVertexCopier gc = new BaseEdgeVertexCopier();
VertexType u;
BaseEdge e;
u = (VertexType) gc.convert(null);
g.insertVertex(u);
for (VertexType v : g) {
if (v != u) {
e = gc.convert(null, u, v);
g.insertEdge((EdgeType) e);
e.setWeight(0);
}
}
BellmanFord sp = new BellmanFord();
if (sp.computePaths(g, u) != null) {
Vector<VertexType> pd = sp.computePaths(g, u);
for (VertexType v : g) {
int dd = 0;
VertexType w = v;
EdgeType h;
while (w != u) {
h = getSingleEdge(g, pd.get(v.getId()), w);
dd += h.getWeight();
}
a[v.getId()] = dd;
}
Iterator<EdgeType> iet = g.edgeIterator();
EdgeType h;
while (iet.hasNext()) {
h = iet.next();
int w = h.getWeight() + a[h.source.getId()] - a[h.target.getId()];
//nw.put(h,w);
h.setWeight(w);
}
for (VertexType v : g) {
Dijkstra dj = new Dijkstra();
Vector<VertexType> pdj = dj.getShortestPath(g, v);
for (VertexType z : g) {
int dd = 0;
VertexType w = z;
EdgeType f;
while (w != v) {
f = getSingleEdge(g, pdj.get(z.getId()), w);
dd += f.getWeight();
}
d[v.getId()][z.getId()] = dd + a[z.getId()] - a[v.getId()];
}
}
}
return new int[0][];
}
private EdgeType getSingleEdge(GraphType g, VertexType v, VertexType w) {
Collection<EdgeType> f;
EdgeType h;
f = g.getEdges(v, w);
h = f.iterator().next();
return h;
}
}