1 | // |
2 | //======================================================================= |
3 | // Copyright 1997, 1998, 1999, 2000 University of Notre Dame. |
4 | // Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek |
5 | // |
6 | // Distributed under the Boost Software License, Version 1.0. (See |
7 | // accompanying file LICENSE_1_0.txt or copy at |
8 | // http://www.boost.org/LICENSE_1_0.txt) |
9 | //======================================================================= |
10 | // |
11 | |
12 | /* |
13 | This file implements the function |
14 | |
15 | template <class EdgeListGraph, class Size, class P, class T, class R> |
16 | bool bellman_ford_shortest_paths(EdgeListGraph& g, Size N, |
17 | const bgl_named_params<P, T, R>& params) |
18 | |
19 | */ |
20 | |
21 | |
22 | #ifndef BOOST_GRAPH_BELLMAN_FORD_SHORTEST_PATHS_HPP |
23 | #define BOOST_GRAPH_BELLMAN_FORD_SHORTEST_PATHS_HPP |
24 | |
25 | #include <boost/config.hpp> |
26 | #include <boost/graph/graph_traits.hpp> |
27 | #include <boost/graph/graph_concepts.hpp> |
28 | #include <boost/graph/properties.hpp> |
29 | #include <boost/graph/relax.hpp> |
30 | #include <boost/graph/visitors.hpp> |
31 | #include <boost/graph/named_function_params.hpp> |
32 | #include <boost/concept/assert.hpp> |
33 | |
34 | namespace boost { |
35 | |
36 | template <class Visitor, class Graph> |
37 | struct BellmanFordVisitorConcept { |
38 | void constraints() { |
39 | BOOST_CONCEPT_ASSERT(( CopyConstructibleConcept<Visitor> )); |
40 | vis.examine_edge(e, g); |
41 | vis.edge_relaxed(e, g); |
42 | vis.edge_not_relaxed(e, g); |
43 | vis.edge_minimized(e, g); |
44 | vis.edge_not_minimized(e, g); |
45 | } |
46 | Visitor vis; |
47 | Graph g; |
48 | typename graph_traits<Graph>::edge_descriptor e; |
49 | }; |
50 | |
51 | template <class Visitors = null_visitor> |
52 | class bellman_visitor { |
53 | public: |
54 | bellman_visitor() { } |
55 | bellman_visitor(Visitors vis) : m_vis(vis) { } |
56 | |
57 | template <class Edge, class Graph> |
58 | void examine_edge(Edge u, Graph& g) { |
59 | invoke_visitors(m_vis, u, g, on_examine_edge()); |
60 | } |
61 | template <class Edge, class Graph> |
62 | void edge_relaxed(Edge u, Graph& g) { |
63 | invoke_visitors(m_vis, u, g, on_edge_relaxed()); |
64 | } |
65 | template <class Edge, class Graph> |
66 | void edge_not_relaxed(Edge u, Graph& g) { |
67 | invoke_visitors(m_vis, u, g, on_edge_not_relaxed()); |
68 | } |
69 | template <class Edge, class Graph> |
70 | void edge_minimized(Edge u, Graph& g) { |
71 | invoke_visitors(m_vis, u, g, on_edge_minimized()); |
72 | } |
73 | template <class Edge, class Graph> |
74 | void edge_not_minimized(Edge u, Graph& g) { |
75 | invoke_visitors(m_vis, u, g, on_edge_not_minimized()); |
76 | } |
77 | protected: |
78 | Visitors m_vis; |
79 | }; |
80 | template <class Visitors> |
81 | bellman_visitor<Visitors> |
82 | make_bellman_visitor(Visitors vis) { |
83 | return bellman_visitor<Visitors>(vis); |
84 | } |
85 | typedef bellman_visitor<> default_bellman_visitor; |
86 | |
87 | template <class EdgeListGraph, class Size, class WeightMap, |
88 | class PredecessorMap, class DistanceMap, |
89 | class BinaryFunction, class BinaryPredicate, |
90 | class BellmanFordVisitor> |
91 | bool bellman_ford_shortest_paths(EdgeListGraph& g, Size N, |
92 | WeightMap weight, |
93 | PredecessorMap pred, |
94 | DistanceMap distance, |
95 | BinaryFunction combine, |
96 | BinaryPredicate compare, |
97 | BellmanFordVisitor v) |
98 | { |
99 | BOOST_CONCEPT_ASSERT(( EdgeListGraphConcept<EdgeListGraph> )); |
100 | typedef graph_traits<EdgeListGraph> GTraits; |
101 | typedef typename GTraits::edge_descriptor Edge; |
102 | typedef typename GTraits::vertex_descriptor Vertex; |
103 | BOOST_CONCEPT_ASSERT(( ReadWritePropertyMapConcept<DistanceMap, Vertex> )); |
104 | BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept<WeightMap, Edge> )); |
105 | |
106 | typename GTraits::edge_iterator i, end; |
107 | |
108 | for (Size k = 0; k < N; ++k) { |
109 | bool at_least_one_edge_relaxed = false; |
110 | for (boost::tie(i, end) = edges(g); i != end; ++i) { |
111 | v.examine_edge(*i, g); |
112 | if (relax(*i, g, weight, pred, distance, combine, compare)) { |
113 | at_least_one_edge_relaxed = true; |
114 | v.edge_relaxed(*i, g); |
115 | } else |
116 | v.edge_not_relaxed(*i, g); |
117 | } |
118 | if (!at_least_one_edge_relaxed) |
119 | break; |
120 | } |
121 | |
122 | for (boost::tie(i, end) = edges(g); i != end; ++i) |
123 | if (compare(combine(get(distance, source(*i, g)), get(weight, *i)), |
124 | get(distance, target(*i,g)))) |
125 | { |
126 | v.edge_not_minimized(*i, g); |
127 | return false; |
128 | } else |
129 | v.edge_minimized(*i, g); |
130 | |
131 | return true; |
132 | } |
133 | |
134 | namespace detail { |
135 | |
136 | template<typename VertexAndEdgeListGraph, typename Size, |
137 | typename WeightMap, typename PredecessorMap, typename DistanceMap, |
138 | typename P, typename T, typename R> |
139 | bool |
140 | bellman_dispatch2 |
141 | (VertexAndEdgeListGraph& g, |
142 | typename graph_traits<VertexAndEdgeListGraph>::vertex_descriptor s, |
143 | Size N, WeightMap weight, PredecessorMap pred, DistanceMap distance, |
144 | const bgl_named_params<P, T, R>& params) |
145 | { |
146 | typedef typename property_traits<DistanceMap>::value_type D; |
147 | bellman_visitor<> null_vis; |
148 | typedef typename property_traits<WeightMap>::value_type weight_type; |
149 | typename graph_traits<VertexAndEdgeListGraph>::vertex_iterator v, v_end; |
150 | for (boost::tie(v, v_end) = vertices(g); v != v_end; ++v) { |
151 | put(distance, *v, (std::numeric_limits<weight_type>::max)()); |
152 | put(pred, *v, *v); |
153 | } |
154 | put(distance, s, weight_type(0)); |
155 | return bellman_ford_shortest_paths |
156 | (g, N, weight, pred, distance, |
157 | choose_param(get_param(params, distance_combine_t()), |
158 | closed_plus<D>()), |
159 | choose_param(get_param(params, distance_compare_t()), |
160 | std::less<D>()), |
161 | choose_param(get_param(params, graph_visitor), |
162 | null_vis) |
163 | ); |
164 | } |
165 | |
166 | template<typename VertexAndEdgeListGraph, typename Size, |
167 | typename WeightMap, typename PredecessorMap, typename DistanceMap, |
168 | typename P, typename T, typename R> |
169 | bool |
170 | bellman_dispatch2 |
171 | (VertexAndEdgeListGraph& g, |
172 | param_not_found, |
173 | Size N, WeightMap weight, PredecessorMap pred, DistanceMap distance, |
174 | const bgl_named_params<P, T, R>& params) |
175 | { |
176 | typedef typename property_traits<DistanceMap>::value_type D; |
177 | bellman_visitor<> null_vis; |
178 | return bellman_ford_shortest_paths |
179 | (g, N, weight, pred, distance, |
180 | choose_param(get_param(params, distance_combine_t()), |
181 | closed_plus<D>()), |
182 | choose_param(get_param(params, distance_compare_t()), |
183 | std::less<D>()), |
184 | choose_param(get_param(params, graph_visitor), |
185 | null_vis) |
186 | ); |
187 | } |
188 | |
189 | template <class EdgeListGraph, class Size, class WeightMap, |
190 | class DistanceMap, class P, class T, class R> |
191 | bool bellman_dispatch(EdgeListGraph& g, Size N, |
192 | WeightMap weight, DistanceMap distance, |
193 | const bgl_named_params<P, T, R>& params) |
194 | { |
195 | dummy_property_map dummy_pred; |
196 | return |
197 | detail::bellman_dispatch2 |
198 | (g, |
199 | get_param(params, root_vertex_t()), |
200 | N, weight, |
201 | choose_param(get_param(params, vertex_predecessor), dummy_pred), |
202 | distance, |
203 | params); |
204 | } |
205 | } // namespace detail |
206 | |
207 | template <class EdgeListGraph, class Size, class P, class T, class R> |
208 | bool bellman_ford_shortest_paths |
209 | (EdgeListGraph& g, Size N, |
210 | const bgl_named_params<P, T, R>& params) |
211 | { |
212 | return detail::bellman_dispatch |
213 | (g, N, |
214 | choose_const_pmap(get_param(params, edge_weight), g, edge_weight), |
215 | choose_pmap(get_param(params, vertex_distance), g, vertex_distance), |
216 | params); |
217 | } |
218 | |
219 | template <class EdgeListGraph, class Size> |
220 | bool bellman_ford_shortest_paths(EdgeListGraph& g, Size N) |
221 | { |
222 | bgl_named_params<int,int> params(0); |
223 | return bellman_ford_shortest_paths(g, N, params); |
224 | } |
225 | |
226 | template <class VertexAndEdgeListGraph, class P, class T, class R> |
227 | bool bellman_ford_shortest_paths |
228 | (VertexAndEdgeListGraph& g, |
229 | const bgl_named_params<P, T, R>& params) |
230 | { |
231 | BOOST_CONCEPT_ASSERT(( VertexListGraphConcept<VertexAndEdgeListGraph> )); |
232 | return detail::bellman_dispatch |
233 | (g, num_vertices(g), |
234 | choose_const_pmap(get_param(params, edge_weight), g, edge_weight), |
235 | choose_pmap(get_param(params, vertex_distance), g, vertex_distance), |
236 | params); |
237 | } |
238 | } // namespace boost |
239 | |
240 | #endif // BOOST_GRAPH_BELLMAN_FORD_SHORTEST_PATHS_HPP |
241 | |