]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 |