// | |
//======================================================================= | |
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. | |
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek | |
// | |
// Distributed under the Boost Software License, Version 1.0. (See | |
// accompanying file LICENSE_1_0.txt or copy at | |
// http://www.boost.org/LICENSE_1_0.txt) | |
//======================================================================= | |
// | |
/* | |
This file implements the function | |
template <class EdgeListGraph, class Size, class P, class T, class R> | |
bool bellman_ford_shortest_paths(EdgeListGraph& g, Size N, | |
const bgl_named_params<P, T, R>& params) | |
*/ | |
#ifndef BOOST_GRAPH_BELLMAN_FORD_SHORTEST_PATHS_HPP | |
#define BOOST_GRAPH_BELLMAN_FORD_SHORTEST_PATHS_HPP | |
#include <boost/config.hpp> | |
#include <boost/graph/graph_traits.hpp> | |
#include <boost/graph/graph_concepts.hpp> | |
#include <boost/graph/properties.hpp> | |
#include <boost/graph/relax.hpp> | |
#include <boost/graph/visitors.hpp> | |
#include <boost/graph/named_function_params.hpp> | |
namespace boost { | |
template <class Visitor, class Graph> | |
struct BellmanFordVisitorConcept { | |
void constraints() { | |
function_requires< CopyConstructibleConcept<Visitor> >(); | |
vis.examine_edge(e, g); | |
vis.edge_relaxed(e, g); | |
vis.edge_not_relaxed(e, g); | |
vis.edge_minimized(e, g); | |
vis.edge_not_minimized(e, g); | |
} | |
Visitor vis; | |
Graph g; | |
typename graph_traits<Graph>::edge_descriptor e; | |
}; | |
template <class Visitors = null_visitor> | |
class bellman_visitor { | |
public: | |
bellman_visitor() { } | |
bellman_visitor(Visitors vis) : m_vis(vis) { } | |
template <class Edge, class Graph> | |
void examine_edge(Edge u, Graph& g) { | |
invoke_visitors(m_vis, u, g, on_examine_edge()); | |
} | |
template <class Edge, class Graph> | |
void edge_relaxed(Edge u, Graph& g) { | |
invoke_visitors(m_vis, u, g, on_edge_relaxed()); | |
} | |
template <class Edge, class Graph> | |
void edge_not_relaxed(Edge u, Graph& g) { | |
invoke_visitors(m_vis, u, g, on_edge_not_relaxed()); | |
} | |
template <class Edge, class Graph> | |
void edge_minimized(Edge u, Graph& g) { | |
invoke_visitors(m_vis, u, g, on_edge_minimized()); | |
} | |
template <class Edge, class Graph> | |
void edge_not_minimized(Edge u, Graph& g) { | |
invoke_visitors(m_vis, u, g, on_edge_not_minimized()); | |
} | |
protected: | |
Visitors m_vis; | |
}; | |
template <class Visitors> | |
bellman_visitor<Visitors> | |
make_bellman_visitor(Visitors vis) { | |
return bellman_visitor<Visitors>(vis); | |
} | |
typedef bellman_visitor<> default_bellman_visitor; | |
template <class EdgeListGraph, class Size, class WeightMap, | |
class PredecessorMap, class DistanceMap, | |
class BinaryFunction, class BinaryPredicate, | |
class BellmanFordVisitor> | |
bool bellman_ford_shortest_paths(EdgeListGraph& g, Size N, | |
WeightMap weight, | |
PredecessorMap pred, | |
DistanceMap distance, | |
BinaryFunction combine, | |
BinaryPredicate compare, | |
BellmanFordVisitor v) | |
{ | |
function_requires<EdgeListGraphConcept<EdgeListGraph> >(); | |
typedef graph_traits<EdgeListGraph> GTraits; | |
typedef typename GTraits::edge_descriptor Edge; | |
typedef typename GTraits::vertex_descriptor Vertex; | |
function_requires<ReadWritePropertyMapConcept<DistanceMap, Vertex> >(); | |
function_requires<ReadablePropertyMapConcept<WeightMap, Edge> >(); | |
typedef typename property_traits<DistanceMap>::value_type D_value; | |
typedef typename property_traits<WeightMap>::value_type W_value; | |
typename GTraits::edge_iterator i, end; | |
for (Size k = 0; k < N; ++k) { | |
bool at_least_one_edge_relaxed = false; | |
for (boost::tie(i, end) = edges(g); i != end; ++i) { | |
v.examine_edge(*i, g); | |
if (relax(*i, g, weight, pred, distance, combine, compare)) { | |
at_least_one_edge_relaxed = true; | |
v.edge_relaxed(*i, g); | |
} else | |
v.edge_not_relaxed(*i, g); | |
} | |
if (!at_least_one_edge_relaxed) | |
break; | |
} | |
for (boost::tie(i, end) = edges(g); i != end; ++i) | |
if (compare(combine(get(distance, source(*i, g)), get(weight, *i)), | |
get(distance, target(*i,g)))) | |
{ | |
v.edge_not_minimized(*i, g); | |
return false; | |
} else | |
v.edge_minimized(*i, g); | |
return true; | |
} | |
namespace detail { | |
template<typename VertexAndEdgeListGraph, typename Size, | |
typename WeightMap, typename PredecessorMap, typename DistanceMap, | |
typename P, typename T, typename R> | |
bool | |
bellman_dispatch2 | |
(VertexAndEdgeListGraph& g, | |
typename graph_traits<VertexAndEdgeListGraph>::vertex_descriptor s, | |
Size N, WeightMap weight, PredecessorMap pred, DistanceMap distance, | |
const bgl_named_params<P, T, R>& params) | |
{ | |
typedef typename property_traits<DistanceMap>::value_type D; | |
bellman_visitor<> null_vis; | |
typedef typename property_traits<WeightMap>::value_type weight_type; | |
typename graph_traits<VertexAndEdgeListGraph>::vertex_iterator v, v_end; | |
for (boost::tie(v, v_end) = vertices(g); v != v_end; ++v) { | |
put(distance, *v, (std::numeric_limits<weight_type>::max)()); | |
put(pred, *v, *v); | |
} | |
put(distance, s, weight_type(0)); | |
return bellman_ford_shortest_paths | |
(g, N, weight, pred, distance, | |
choose_param(get_param(params, distance_combine_t()), | |
closed_plus<D>()), | |
choose_param(get_param(params, distance_compare_t()), | |
std::less<D>()), | |
choose_param(get_param(params, graph_visitor), | |
null_vis) | |
); | |
} | |
template<typename VertexAndEdgeListGraph, typename Size, | |
typename WeightMap, typename PredecessorMap, typename DistanceMap, | |
typename P, typename T, typename R> | |
bool | |
bellman_dispatch2 | |
(VertexAndEdgeListGraph& g, | |
detail::error_property_not_found, | |
Size N, WeightMap weight, PredecessorMap pred, DistanceMap distance, | |
const bgl_named_params<P, T, R>& params) | |
{ | |
typedef typename property_traits<DistanceMap>::value_type D; | |
bellman_visitor<> null_vis; | |
return bellman_ford_shortest_paths | |
(g, N, weight, pred, distance, | |
choose_param(get_param(params, distance_combine_t()), | |
closed_plus<D>()), | |
choose_param(get_param(params, distance_compare_t()), | |
std::less<D>()), | |
choose_param(get_param(params, graph_visitor), | |
null_vis) | |
); | |
} | |
template <class EdgeListGraph, class Size, class WeightMap, | |
class DistanceMap, class P, class T, class R> | |
bool bellman_dispatch(EdgeListGraph& g, Size N, | |
WeightMap weight, DistanceMap distance, | |
const bgl_named_params<P, T, R>& params) | |
{ | |
dummy_property_map dummy_pred; | |
return | |
detail::bellman_dispatch2 | |
(g, | |
get_param(params, root_vertex_t()), | |
N, weight, | |
choose_param(get_param(params, vertex_predecessor), dummy_pred), | |
distance, | |
params); | |
} | |
} // namespace detail | |
template <class EdgeListGraph, class Size, class P, class T, class R> | |
bool bellman_ford_shortest_paths | |
(EdgeListGraph& g, Size N, | |
const bgl_named_params<P, T, R>& params) | |
{ | |
return detail::bellman_dispatch | |
(g, N, | |
choose_const_pmap(get_param(params, edge_weight), g, edge_weight), | |
choose_pmap(get_param(params, vertex_distance), g, vertex_distance), | |
params); | |
} | |
template <class EdgeListGraph, class Size> | |
bool bellman_ford_shortest_paths(EdgeListGraph& g, Size N) | |
{ | |
bgl_named_params<int,int> params(0); | |
return bellman_ford_shortest_paths(g, N, params); | |
} | |
template <class VertexAndEdgeListGraph, class P, class T, class R> | |
bool bellman_ford_shortest_paths | |
(VertexAndEdgeListGraph& g, | |
const bgl_named_params<P, T, R>& params) | |
{ | |
function_requires<VertexListGraphConcept<VertexAndEdgeListGraph> >(); | |
return detail::bellman_dispatch | |
(g, num_vertices(g), | |
choose_const_pmap(get_param(params, edge_weight), g, edge_weight), | |
choose_pmap(get_param(params, vertex_distance), g, vertex_distance), | |
params); | |
} | |
} // namespace boost | |
#endif // BOOST_GRAPH_BELLMAN_FORD_SHORTEST_PATHS_HPP |