williamr@2: //======================================================================= williamr@2: // Copyright 1997, 1998, 1999, 2000 University of Notre Dame. williamr@2: // Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek williamr@2: // williamr@2: // Distributed under the Boost Software License, Version 1.0. (See williamr@2: // accompanying file LICENSE_1_0.txt or copy at williamr@2: // http://www.boost.org/LICENSE_1_0.txt) williamr@2: //======================================================================= williamr@2: williamr@2: /* williamr@2: This file implements the function williamr@2: williamr@2: template williamr@2: bool williamr@2: johnson_all_pairs_shortest_paths williamr@2: (VertexAndEdgeListGraph& g, williamr@2: DistanceMatrix& D, williamr@2: const bgl_named_params& params) williamr@2: */ williamr@2: williamr@2: #ifndef BOOST_GRAPH_JOHNSON_HPP williamr@2: #define BOOST_GRAPH_JOHNSON_HPP williamr@2: williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: williamr@2: namespace boost { williamr@2: williamr@2: template williamr@2: bool williamr@2: johnson_all_pairs_shortest_paths(VertexAndEdgeListGraph& g1, williamr@2: DistanceMatrix& D, williamr@2: VertexID id1, Weight w1, const BinaryPredicate& compare, williamr@2: const BinaryFunction& combine, const Infinity& inf, williamr@2: DistanceZero zero) williamr@2: { williamr@2: typedef graph_traits Traits1; williamr@2: typedef typename property_traits::value_type DT; williamr@2: function_requires< BasicMatrixConcept >(); williamr@2: williamr@2: typedef typename Traits1::directed_category DirCat; williamr@2: bool is_undirected = is_same::value; williamr@2: williamr@2: typedef adjacency_list, williamr@2: property< edge_weight_t, DT, williamr@2: property< edge_weight2_t, DT > > > Graph2; williamr@2: typedef graph_traits Traits2; williamr@2: williamr@2: Graph2 g2(num_vertices(g1) + 1); williamr@2: typename property_map::type williamr@2: w = get(edge_weight, g2); williamr@2: typename property_map::type williamr@2: w_hat = get(edge_weight2, g2); williamr@2: typename property_map::type williamr@2: d = get(vertex_distance, g2); williamr@2: typedef typename property_map::type VertexID2; williamr@2: VertexID2 id2 = get(vertex_index, g2); williamr@2: williamr@2: // Construct g2 where V[g2] = V[g1] U {s} williamr@2: // and E[g2] = E[g1] U {(s,v)| v in V[g1]} williamr@2: std::vector williamr@2: verts1(num_vertices(g1) + 1); williamr@2: typename Traits2::vertex_descriptor s = *vertices(g2).first; williamr@2: { williamr@2: typename Traits1::vertex_iterator v, v_end; williamr@2: int i = 1; williamr@2: for (tie(v, v_end) = vertices(g1); v != v_end; ++v, ++i) { williamr@2: typename Traits2::edge_descriptor e; bool z; williamr@2: tie(e, z) = add_edge(s, get(id1, *v) + 1, g2); williamr@2: put(w, e, zero); williamr@2: verts1[i] = *v; williamr@2: } williamr@2: typename Traits1::edge_iterator e, e_end; williamr@2: for (tie(e, e_end) = edges(g1); e != e_end; ++e) { williamr@2: typename Traits2::edge_descriptor e2; bool z; williamr@2: tie(e2, z) = add_edge(get(id1, source(*e, g1)) + 1, williamr@2: get(id1, target(*e, g1)) + 1, g2); williamr@2: put(w, e2, get(w1, *e)); williamr@2: if (is_undirected) { williamr@2: tie(e2, z) = add_edge(get(id1, target(*e, g1)) + 1, williamr@2: get(id1, source(*e, g1)) + 1, g2); williamr@2: put(w, e2, get(w1, *e)); williamr@2: } williamr@2: } williamr@2: } williamr@2: typename Traits2::vertex_iterator v, v_end, u, u_end; williamr@2: typename Traits2::edge_iterator e, e_end; williamr@2: std::vector
h_vec(num_vertices(g2)); williamr@2: typedef typename std::vector
::iterator iter_t; williamr@2: iterator_property_map h(h_vec.begin(), id2); williamr@2: williamr@2: for (tie(v, v_end) = vertices(g2); v != v_end; ++v) williamr@2: d[*v] = inf; williamr@2: williamr@2: put(d, s, zero); williamr@2: // Using the non-named parameter versions of bellman_ford and williamr@2: // dijkstra for portability reasons. williamr@2: dummy_property_map pred; bellman_visitor<> bvis; williamr@2: if (bellman_ford_shortest_paths williamr@2: (g2, num_vertices(g2), w, pred, d, combine, compare, bvis)) { williamr@2: for (tie(v, v_end) = vertices(g2); v != v_end; ++v) williamr@2: put(h, *v, get(d, *v)); williamr@2: // Reweight the edges to remove negatives williamr@2: for (tie(e, e_end) = edges(g2); e != e_end; ++e) { williamr@2: typename Traits2::vertex_descriptor a = source(*e, g2), williamr@2: b = target(*e, g2); williamr@2: put(w_hat, *e, get(w, *e) + get(h, a) - get(h, b)); williamr@2: } williamr@2: for (tie(u, u_end) = vertices(g2); u != u_end; ++u) { williamr@2: dijkstra_visitor<> dvis; williamr@2: dijkstra_shortest_paths williamr@2: (g2, *u, pred, d, w_hat, id2, compare, combine, inf, zero,dvis); williamr@2: for (tie(v, v_end) = vertices(g2); v != v_end; ++v) { williamr@2: if (*u != s && *v != s) { williamr@2: typename Traits1::vertex_descriptor u1, v1; williamr@2: u1 = verts1[id2[*u]]; v1 = verts1[id2[*v]]; williamr@2: D[id2[*u]-1][id2[*v]-1] = get(d, *v) + get(h, *v) - get(h, *u); williamr@2: } williamr@2: } williamr@2: } williamr@2: return true; williamr@2: } else williamr@2: return false; williamr@2: } williamr@2: williamr@2: template williamr@2: bool williamr@2: johnson_all_pairs_shortest_paths(VertexAndEdgeListGraph& g1, williamr@2: DistanceMatrix& D, williamr@2: VertexID id1, Weight w1, DistanceZero zero) williamr@2: { williamr@2: typedef typename property_traits::value_type WT; williamr@2: return johnson_all_pairs_shortest_paths(g1, D, id1, w1, williamr@2: std::less(), williamr@2: closed_plus(), williamr@2: (std::numeric_limits::max)(), williamr@2: zero); williamr@2: } williamr@2: williamr@2: namespace detail { williamr@2: williamr@2: template williamr@2: bool williamr@2: johnson_dispatch(VertexAndEdgeListGraph& g, williamr@2: DistanceMatrix& D, williamr@2: const bgl_named_params& params, williamr@2: Weight w, VertexID id) williamr@2: { williamr@2: typedef typename property_traits::value_type WT; williamr@2: williamr@2: return johnson_all_pairs_shortest_paths williamr@2: (g, D, id, w, williamr@2: choose_param(get_param(params, distance_compare_t()), williamr@2: std::less()), williamr@2: choose_param(get_param(params, distance_combine_t()), williamr@2: closed_plus()), williamr@2: choose_param(get_param(params, distance_inf_t()), williamr@2: std::numeric_limits::max BOOST_PREVENT_MACRO_SUBSTITUTION()), williamr@2: choose_param(get_param(params, distance_zero_t()), WT()) ); williamr@2: } williamr@2: williamr@2: } // namespace detail williamr@2: williamr@2: template williamr@2: bool williamr@2: johnson_all_pairs_shortest_paths williamr@2: (VertexAndEdgeListGraph& g, williamr@2: DistanceMatrix& D, williamr@2: const bgl_named_params& params) williamr@2: { williamr@2: return detail::johnson_dispatch williamr@2: (g, D, params, williamr@2: choose_const_pmap(get_param(params, edge_weight), g, edge_weight), williamr@2: choose_const_pmap(get_param(params, vertex_index), g, vertex_index) williamr@2: ); williamr@2: } williamr@2: williamr@2: template williamr@2: bool williamr@2: johnson_all_pairs_shortest_paths williamr@2: (VertexAndEdgeListGraph& g, DistanceMatrix& D) williamr@2: { williamr@2: bgl_named_params params(1); williamr@2: return detail::johnson_dispatch williamr@2: (g, D, params, get(edge_weight, g), get(vertex_index, g)); williamr@2: } williamr@2: williamr@2: } // namespace boost williamr@2: williamr@2: #endif // BOOST_GRAPH_JOHNSON_HPP williamr@2: williamr@2: