// Copyright 2003, Trustees of Indiana University // Please see the license in the file ../LICENSE using GCollections; public class null_property_map: ReadWritePropertyMap { public B this[A a] { get {throw new System.Exception();} set {} } } public class johnson_all_pairs_shortest_paths { public static bool go (Graph g, WeightMap w, WeightMap2 w2, DistanceMap distance, DistanceMatrix distance_matrix, Distance zero, Distance inf, DistanceCombine combine, DistanceNegate negate, DistanceCompare compare) where Graph: VertexListAndIncidenceAndEdgeListGraph, Edge: GraphEdge, VertexIterator: IEnumerable, OutEdgeIterator: IEnumerable, EdgeIterator: IEnumerable, WeightMap: ReadablePropertyMap, WeightMap2: ReadWritePropertyMap, DistanceMap: ReadWritePropertyMap, DistanceMatrixElement: ReadWritePropertyMap, DistanceMatrix: ReadablePropertyMap, DistanceCombine: BinaryFunction, DistanceCompare: StrictWeakOrdering, DistanceNegate: UnaryFunction { // Set distance to all vertices to zero (emulates special "s" vertex used in CLR) for (IEnumerator vi = g.vertices().GetEnumerator(); vi.MoveNext();) { Vertex v = vi.Current; ((ReadWritePropertyMap)distance)[v] = zero; } // Do Bellman-Ford to get factors for reweighting bool bf_worked = bellman_ford_shortest_paths.go< Graph, Vertex, Edge, EdgeIterator, Distance, WeightMap, null_property_map, DistanceMap, DistanceCombine, DistanceCompare> (g, g.num_vertices(), w, new null_property_map(), distance, combine, compare); if (!bf_worked) return false; // Negative-weight cycle // Set up reweighting for (IEnumerator ei = g.edges().GetEnumerator(); ei.MoveNext();) { Edge e = ei.Current; ((ReadWritePropertyMap)w2)[e] = combine.op(combine.op(((ReadablePropertyMap)w)[e], ((ReadWritePropertyMap)distance)[e.source]), negate.op(((ReadWritePropertyMap)distance)[e.target])); } // Do Dijkstra from each vertex for (IEnumerator vi = g.vertices().GetEnumerator(); vi.MoveNext();) { Vertex v = vi.Current; DistanceMatrixElement dm = ((ReadablePropertyMap)distance_matrix)[v]; dijkstra_shortest_paths.go< Graph, Vertex, Edge, VertexIterator, OutEdgeIterator, WeightMap2, DistanceMatrixElement, Distance, null_property_map, DistanceCombine, DistanceCompare> (g, v, new null_property_map(), dm, w2, compare, combine, inf, zero); // Adjust returned distances to account for reweighting for (IEnumerator vi2 = g.vertices().GetEnumerator(); vi2.MoveNext();) { Vertex v2 = vi2.Current; ((ReadWritePropertyMap)dm)[v2] = combine.op(combine.op(((ReadWritePropertyMap)dm)[v2], ((ReadWritePropertyMap)distance)[v2]), negate.op(((ReadWritePropertyMap)distance)[v])); } } return true; } }