Chris@16
|
1 // r_c_shortest_paths.hpp header file
|
Chris@16
|
2
|
Chris@16
|
3 // Copyright Michael Drexl 2005, 2006.
|
Chris@16
|
4 // Distributed under the Boost Software License, Version 1.0.
|
Chris@16
|
5 // (See accompanying file LICENSE_1_0.txt or copy at
|
Chris@16
|
6 // http://boost.org/LICENSE_1_0.txt)
|
Chris@16
|
7
|
Chris@16
|
8 #ifndef BOOST_GRAPH_R_C_SHORTEST_PATHS_HPP
|
Chris@16
|
9 #define BOOST_GRAPH_R_C_SHORTEST_PATHS_HPP
|
Chris@16
|
10
|
Chris@16
|
11 #include <map>
|
Chris@16
|
12 #include <queue>
|
Chris@16
|
13 #include <vector>
|
Chris@16
|
14
|
Chris@16
|
15 #include <boost/graph/graph_traits.hpp>
|
Chris@101
|
16 #include <boost/graph/iteration_macros.hpp>
|
Chris@101
|
17 #include <boost/property_map/property_map.hpp>
|
Chris@16
|
18
|
Chris@16
|
19 namespace boost {
|
Chris@16
|
20
|
Chris@16
|
21 // r_c_shortest_paths_label struct
|
Chris@16
|
22 template<class Graph, class Resource_Container>
|
Chris@16
|
23 struct r_c_shortest_paths_label
|
Chris@16
|
24 {
|
Chris@16
|
25 r_c_shortest_paths_label
|
Chris@16
|
26 ( const unsigned long n,
|
Chris@16
|
27 const Resource_Container& rc = Resource_Container(),
|
Chris@16
|
28 const r_c_shortest_paths_label* const pl = 0,
|
Chris@16
|
29 const typename graph_traits<Graph>::edge_descriptor& ed =
|
Chris@16
|
30 graph_traits<Graph>::edge_descriptor(),
|
Chris@16
|
31 const typename graph_traits<Graph>::vertex_descriptor& vd =
|
Chris@16
|
32 graph_traits<Graph>::vertex_descriptor() )
|
Chris@16
|
33 : num( n ),
|
Chris@16
|
34 cumulated_resource_consumption( rc ),
|
Chris@16
|
35 p_pred_label( pl ),
|
Chris@16
|
36 pred_edge( ed ),
|
Chris@16
|
37 resident_vertex( vd ),
|
Chris@16
|
38 b_is_dominated( false ),
|
Chris@101
|
39 b_is_processed( false ),
|
Chris@101
|
40 b_is_valid( true )
|
Chris@16
|
41 {}
|
Chris@16
|
42 r_c_shortest_paths_label& operator=( const r_c_shortest_paths_label& other )
|
Chris@16
|
43 {
|
Chris@16
|
44 if( this == &other )
|
Chris@16
|
45 return *this;
|
Chris@16
|
46 this->~r_c_shortest_paths_label();
|
Chris@16
|
47 new( this ) r_c_shortest_paths_label( other );
|
Chris@16
|
48 return *this;
|
Chris@16
|
49 }
|
Chris@16
|
50 const unsigned long num;
|
Chris@16
|
51 Resource_Container cumulated_resource_consumption;
|
Chris@16
|
52 const r_c_shortest_paths_label* const p_pred_label;
|
Chris@16
|
53 const typename graph_traits<Graph>::edge_descriptor pred_edge;
|
Chris@16
|
54 const typename graph_traits<Graph>::vertex_descriptor resident_vertex;
|
Chris@16
|
55 bool b_is_dominated;
|
Chris@16
|
56 bool b_is_processed;
|
Chris@101
|
57 bool b_is_valid;
|
Chris@16
|
58 }; // r_c_shortest_paths_label
|
Chris@16
|
59
|
Chris@16
|
60 template<class Graph, class Resource_Container>
|
Chris@16
|
61 inline bool operator==
|
Chris@16
|
62 ( const r_c_shortest_paths_label<Graph, Resource_Container>& l1,
|
Chris@16
|
63 const r_c_shortest_paths_label<Graph, Resource_Container>& l2 )
|
Chris@16
|
64 {
|
Chris@101
|
65 assert (l1.b_is_valid && l2.b_is_valid);
|
Chris@16
|
66 return
|
Chris@16
|
67 l1.cumulated_resource_consumption == l2.cumulated_resource_consumption;
|
Chris@16
|
68 }
|
Chris@16
|
69
|
Chris@16
|
70 template<class Graph, class Resource_Container>
|
Chris@16
|
71 inline bool operator!=
|
Chris@16
|
72 ( const r_c_shortest_paths_label<Graph, Resource_Container>& l1,
|
Chris@16
|
73 const r_c_shortest_paths_label<Graph, Resource_Container>& l2 )
|
Chris@16
|
74 {
|
Chris@101
|
75 assert (l1.b_is_valid && l2.b_is_valid);
|
Chris@16
|
76 return
|
Chris@16
|
77 !( l1 == l2 );
|
Chris@16
|
78 }
|
Chris@16
|
79
|
Chris@16
|
80 template<class Graph, class Resource_Container>
|
Chris@16
|
81 inline bool operator<
|
Chris@16
|
82 ( const r_c_shortest_paths_label<Graph, Resource_Container>& l1,
|
Chris@16
|
83 const r_c_shortest_paths_label<Graph, Resource_Container>& l2 )
|
Chris@16
|
84 {
|
Chris@101
|
85 assert (l1.b_is_valid && l2.b_is_valid);
|
Chris@16
|
86 return
|
Chris@16
|
87 l1.cumulated_resource_consumption < l2.cumulated_resource_consumption;
|
Chris@16
|
88 }
|
Chris@16
|
89
|
Chris@16
|
90 template<class Graph, class Resource_Container>
|
Chris@16
|
91 inline bool operator>
|
Chris@16
|
92 ( const r_c_shortest_paths_label<Graph, Resource_Container>& l1,
|
Chris@16
|
93 const r_c_shortest_paths_label<Graph, Resource_Container>& l2 )
|
Chris@16
|
94 {
|
Chris@101
|
95 assert (l1.b_is_valid && l2.b_is_valid);
|
Chris@16
|
96 return
|
Chris@16
|
97 l2.cumulated_resource_consumption < l1.cumulated_resource_consumption;
|
Chris@16
|
98 }
|
Chris@16
|
99
|
Chris@16
|
100 template<class Graph, class Resource_Container>
|
Chris@16
|
101 inline bool operator<=
|
Chris@16
|
102 ( const r_c_shortest_paths_label<Graph, Resource_Container>& l1,
|
Chris@16
|
103 const r_c_shortest_paths_label<Graph, Resource_Container>& l2 )
|
Chris@16
|
104 {
|
Chris@101
|
105 assert (l1.b_is_valid && l2.b_is_valid);
|
Chris@16
|
106 return
|
Chris@16
|
107 l1 < l2 || l1 == l2;
|
Chris@16
|
108 }
|
Chris@16
|
109
|
Chris@16
|
110 template<class Graph, class Resource_Container>
|
Chris@16
|
111 inline bool operator>=
|
Chris@16
|
112 ( const r_c_shortest_paths_label<Graph, Resource_Container>& l1,
|
Chris@16
|
113 const r_c_shortest_paths_label<Graph, Resource_Container>& l2 )
|
Chris@16
|
114 {
|
Chris@101
|
115 assert (l1.b_is_valid && l2.b_is_valid);
|
Chris@16
|
116 return l2 < l1 || l1 == l2;
|
Chris@16
|
117 }
|
Chris@16
|
118
|
Chris@16
|
119 namespace detail {
|
Chris@16
|
120
|
Chris@16
|
121 // ks_smart_pointer class
|
Chris@16
|
122 // from:
|
Chris@16
|
123 // Kuhlins, S.; Schader, M. (1999):
|
Chris@16
|
124 // Die C++-Standardbibliothek
|
Chris@16
|
125 // Springer, Berlin
|
Chris@16
|
126 // p. 333 f.
|
Chris@16
|
127 template<class T>
|
Chris@16
|
128 class ks_smart_pointer
|
Chris@16
|
129 {
|
Chris@16
|
130 public:
|
Chris@16
|
131 ks_smart_pointer( T* ptt = 0 ) : pt( ptt ) {}
|
Chris@16
|
132 ks_smart_pointer( const ks_smart_pointer& other ) : pt( other.pt ) {}
|
Chris@16
|
133 ks_smart_pointer& operator=( const ks_smart_pointer& other )
|
Chris@16
|
134 { pt = other.pt; return *this; }
|
Chris@16
|
135 ~ks_smart_pointer() {}
|
Chris@16
|
136 T& operator*() const { return *pt; }
|
Chris@16
|
137 T* operator->() const { return pt; }
|
Chris@16
|
138 T* get() const { return pt; }
|
Chris@16
|
139 operator T*() const { return pt; }
|
Chris@16
|
140 friend bool operator==( const ks_smart_pointer& t,
|
Chris@16
|
141 const ks_smart_pointer& u )
|
Chris@16
|
142 { return *t.pt == *u.pt; }
|
Chris@16
|
143 friend bool operator!=( const ks_smart_pointer& t,
|
Chris@16
|
144 const ks_smart_pointer& u )
|
Chris@16
|
145 { return *t.pt != *u.pt; }
|
Chris@16
|
146 friend bool operator<( const ks_smart_pointer& t,
|
Chris@16
|
147 const ks_smart_pointer& u )
|
Chris@16
|
148 { return *t.pt < *u.pt; }
|
Chris@16
|
149 friend bool operator>( const ks_smart_pointer& t,
|
Chris@16
|
150 const ks_smart_pointer& u )
|
Chris@16
|
151 { return *t.pt > *u.pt; }
|
Chris@16
|
152 friend bool operator<=( const ks_smart_pointer& t,
|
Chris@16
|
153 const ks_smart_pointer& u )
|
Chris@16
|
154 { return *t.pt <= *u.pt; }
|
Chris@16
|
155 friend bool operator>=( const ks_smart_pointer& t,
|
Chris@16
|
156 const ks_smart_pointer& u )
|
Chris@16
|
157 { return *t.pt >= *u.pt; }
|
Chris@16
|
158 private:
|
Chris@16
|
159 T* pt;
|
Chris@16
|
160 }; // ks_smart_pointer
|
Chris@16
|
161
|
Chris@16
|
162
|
Chris@16
|
163 // r_c_shortest_paths_dispatch function (body/implementation)
|
Chris@16
|
164 template<class Graph,
|
Chris@16
|
165 class VertexIndexMap,
|
Chris@16
|
166 class EdgeIndexMap,
|
Chris@16
|
167 class Resource_Container,
|
Chris@16
|
168 class Resource_Extension_Function,
|
Chris@16
|
169 class Dominance_Function,
|
Chris@16
|
170 class Label_Allocator,
|
Chris@16
|
171 class Visitor>
|
Chris@16
|
172 void r_c_shortest_paths_dispatch
|
Chris@16
|
173 ( const Graph& g,
|
Chris@16
|
174 const VertexIndexMap& vertex_index_map,
|
Chris@16
|
175 const EdgeIndexMap& /*edge_index_map*/,
|
Chris@16
|
176 typename graph_traits<Graph>::vertex_descriptor s,
|
Chris@16
|
177 typename graph_traits<Graph>::vertex_descriptor t,
|
Chris@16
|
178 // each inner vector corresponds to a pareto-optimal path
|
Chris@16
|
179 std::vector
|
Chris@16
|
180 <std::vector
|
Chris@16
|
181 <typename graph_traits
|
Chris@16
|
182 <Graph>::edge_descriptor> >& pareto_optimal_solutions,
|
Chris@16
|
183 std::vector
|
Chris@16
|
184 <Resource_Container>& pareto_optimal_resource_containers,
|
Chris@16
|
185 bool b_all_pareto_optimal_solutions,
|
Chris@16
|
186 // to initialize the first label/resource container
|
Chris@16
|
187 // and to carry the type information
|
Chris@16
|
188 const Resource_Container& rc,
|
Chris@16
|
189 Resource_Extension_Function& ref,
|
Chris@16
|
190 Dominance_Function& dominance,
|
Chris@16
|
191 // to specify the memory management strategy for the labels
|
Chris@16
|
192 Label_Allocator /*la*/,
|
Chris@16
|
193 Visitor vis )
|
Chris@16
|
194 {
|
Chris@16
|
195 pareto_optimal_resource_containers.clear();
|
Chris@16
|
196 pareto_optimal_solutions.clear();
|
Chris@16
|
197
|
Chris@16
|
198 size_t i_label_num = 0;
|
Chris@16
|
199 typedef
|
Chris@16
|
200 typename
|
Chris@16
|
201 Label_Allocator::template rebind
|
Chris@16
|
202 <r_c_shortest_paths_label
|
Chris@16
|
203 <Graph, Resource_Container> >::other LAlloc;
|
Chris@16
|
204 LAlloc l_alloc;
|
Chris@16
|
205 typedef
|
Chris@16
|
206 ks_smart_pointer
|
Chris@16
|
207 <r_c_shortest_paths_label<Graph, Resource_Container> > Splabel;
|
Chris@16
|
208 std::priority_queue<Splabel, std::vector<Splabel>, std::greater<Splabel> >
|
Chris@16
|
209 unprocessed_labels;
|
Chris@16
|
210
|
Chris@16
|
211 bool b_feasible = true;
|
Chris@16
|
212 r_c_shortest_paths_label<Graph, Resource_Container>* first_label =
|
Chris@16
|
213 l_alloc.allocate( 1 );
|
Chris@16
|
214 l_alloc.construct
|
Chris@16
|
215 ( first_label,
|
Chris@16
|
216 r_c_shortest_paths_label
|
Chris@16
|
217 <Graph, Resource_Container>( i_label_num++,
|
Chris@16
|
218 rc,
|
Chris@16
|
219 0,
|
Chris@16
|
220 typename graph_traits<Graph>::
|
Chris@16
|
221 edge_descriptor(),
|
Chris@16
|
222 s ) );
|
Chris@16
|
223
|
Chris@16
|
224 Splabel splabel_first_label = Splabel( first_label );
|
Chris@16
|
225 unprocessed_labels.push( splabel_first_label );
|
Chris@101
|
226 std::vector<std::list<Splabel> > vec_vertex_labels_data( num_vertices( g ) );
|
Chris@101
|
227 iterator_property_map<typename std::vector<std::list<Splabel> >::iterator,
|
Chris@101
|
228 VertexIndexMap>
|
Chris@101
|
229 vec_vertex_labels(vec_vertex_labels_data.begin(), vertex_index_map);
|
Chris@101
|
230 vec_vertex_labels[s].push_back( splabel_first_label );
|
Chris@101
|
231 typedef
|
Chris@101
|
232 std::vector<typename std::list<Splabel>::iterator>
|
Chris@101
|
233 vec_last_valid_positions_for_dominance_data_type;
|
Chris@101
|
234 vec_last_valid_positions_for_dominance_data_type
|
Chris@101
|
235 vec_last_valid_positions_for_dominance_data( num_vertices( g ) );
|
Chris@101
|
236 iterator_property_map<
|
Chris@101
|
237 typename vec_last_valid_positions_for_dominance_data_type::iterator,
|
Chris@101
|
238 VertexIndexMap>
|
Chris@101
|
239 vec_last_valid_positions_for_dominance
|
Chris@101
|
240 (vec_last_valid_positions_for_dominance_data.begin(),
|
Chris@101
|
241 vertex_index_map);
|
Chris@101
|
242 BGL_FORALL_VERTICES_T(v, g, Graph) {
|
Chris@101
|
243 put(vec_last_valid_positions_for_dominance, v, vec_vertex_labels[v].begin());
|
Chris@101
|
244 }
|
Chris@101
|
245 std::vector<size_t> vec_last_valid_index_for_dominance_data( num_vertices( g ), 0 );
|
Chris@101
|
246 iterator_property_map<std::vector<size_t>::iterator, VertexIndexMap>
|
Chris@101
|
247 vec_last_valid_index_for_dominance
|
Chris@101
|
248 (vec_last_valid_index_for_dominance_data.begin(), vertex_index_map);
|
Chris@16
|
249 std::vector<bool>
|
Chris@101
|
250 b_vec_vertex_already_checked_for_dominance_data( num_vertices( g ), false );
|
Chris@101
|
251 iterator_property_map<std::vector<bool>::iterator, VertexIndexMap>
|
Chris@101
|
252 b_vec_vertex_already_checked_for_dominance
|
Chris@101
|
253 (b_vec_vertex_already_checked_for_dominance_data.begin(),
|
Chris@101
|
254 vertex_index_map);
|
Chris@101
|
255
|
Chris@16
|
256 while( !unprocessed_labels.empty() && vis.on_enter_loop(unprocessed_labels, g) )
|
Chris@16
|
257 {
|
Chris@16
|
258 Splabel cur_label = unprocessed_labels.top();
|
Chris@101
|
259 assert (cur_label->b_is_valid);
|
Chris@16
|
260 unprocessed_labels.pop();
|
Chris@16
|
261 vis.on_label_popped( *cur_label, g );
|
Chris@16
|
262 // an Splabel object in unprocessed_labels and the respective Splabel
|
Chris@16
|
263 // object in the respective list<Splabel> of vec_vertex_labels share their
|
Chris@16
|
264 // embedded r_c_shortest_paths_label object
|
Chris@16
|
265 // to avoid memory leaks, dominated
|
Chris@16
|
266 // r_c_shortest_paths_label objects are marked and deleted when popped
|
Chris@16
|
267 // from unprocessed_labels, as they can no longer be deleted at the end of
|
Chris@16
|
268 // the function; only the Splabel object in unprocessed_labels still
|
Chris@16
|
269 // references the r_c_shortest_paths_label object
|
Chris@16
|
270 // this is also for efficiency, because the else branch is executed only
|
Chris@16
|
271 // if there is a chance that extending the
|
Chris@16
|
272 // label leads to new undominated labels, which in turn is possible only
|
Chris@16
|
273 // if the label to be extended is undominated
|
Chris@101
|
274 assert (cur_label->b_is_valid);
|
Chris@16
|
275 if( !cur_label->b_is_dominated )
|
Chris@16
|
276 {
|
Chris@101
|
277 typename boost::graph_traits<Graph>::vertex_descriptor
|
Chris@101
|
278 i_cur_resident_vertex = cur_label->resident_vertex;
|
Chris@16
|
279 std::list<Splabel>& list_labels_cur_vertex =
|
Chris@101
|
280 get(vec_vertex_labels, i_cur_resident_vertex);
|
Chris@16
|
281 if( list_labels_cur_vertex.size() >= 2
|
Chris@101
|
282 && vec_last_valid_index_for_dominance[i_cur_resident_vertex]
|
Chris@16
|
283 < list_labels_cur_vertex.size() )
|
Chris@16
|
284 {
|
Chris@16
|
285 typename std::list<Splabel>::iterator outer_iter =
|
Chris@16
|
286 list_labels_cur_vertex.begin();
|
Chris@16
|
287 bool b_outer_iter_at_or_beyond_last_valid_pos_for_dominance = false;
|
Chris@16
|
288 while( outer_iter != list_labels_cur_vertex.end() )
|
Chris@16
|
289 {
|
Chris@16
|
290 Splabel cur_outer_splabel = *outer_iter;
|
Chris@101
|
291 assert (cur_outer_splabel->b_is_valid);
|
Chris@16
|
292 typename std::list<Splabel>::iterator inner_iter = outer_iter;
|
Chris@16
|
293 if( !b_outer_iter_at_or_beyond_last_valid_pos_for_dominance
|
Chris@16
|
294 && outer_iter ==
|
Chris@101
|
295 get(vec_last_valid_positions_for_dominance,
|
Chris@101
|
296 i_cur_resident_vertex) )
|
Chris@16
|
297 b_outer_iter_at_or_beyond_last_valid_pos_for_dominance = true;
|
Chris@101
|
298 if( !get(b_vec_vertex_already_checked_for_dominance, i_cur_resident_vertex)
|
Chris@16
|
299 || b_outer_iter_at_or_beyond_last_valid_pos_for_dominance )
|
Chris@16
|
300 {
|
Chris@16
|
301 ++inner_iter;
|
Chris@16
|
302 }
|
Chris@16
|
303 else
|
Chris@16
|
304 {
|
Chris@16
|
305 inner_iter =
|
Chris@101
|
306 get(vec_last_valid_positions_for_dominance,
|
Chris@101
|
307 i_cur_resident_vertex);
|
Chris@16
|
308 ++inner_iter;
|
Chris@16
|
309 }
|
Chris@16
|
310 bool b_outer_iter_erased = false;
|
Chris@16
|
311 while( inner_iter != list_labels_cur_vertex.end() )
|
Chris@16
|
312 {
|
Chris@16
|
313 Splabel cur_inner_splabel = *inner_iter;
|
Chris@101
|
314 assert (cur_inner_splabel->b_is_valid);
|
Chris@16
|
315 if( dominance( cur_outer_splabel->
|
Chris@16
|
316 cumulated_resource_consumption,
|
Chris@16
|
317 cur_inner_splabel->
|
Chris@16
|
318 cumulated_resource_consumption ) )
|
Chris@16
|
319 {
|
Chris@16
|
320 typename std::list<Splabel>::iterator buf = inner_iter;
|
Chris@16
|
321 ++inner_iter;
|
Chris@16
|
322 list_labels_cur_vertex.erase( buf );
|
Chris@16
|
323 if( cur_inner_splabel->b_is_processed )
|
Chris@16
|
324 {
|
Chris@101
|
325 cur_inner_splabel->b_is_valid = false;
|
Chris@16
|
326 l_alloc.destroy( cur_inner_splabel.get() );
|
Chris@16
|
327 l_alloc.deallocate( cur_inner_splabel.get(), 1 );
|
Chris@16
|
328 }
|
Chris@16
|
329 else
|
Chris@16
|
330 cur_inner_splabel->b_is_dominated = true;
|
Chris@16
|
331 continue;
|
Chris@16
|
332 }
|
Chris@16
|
333 else
|
Chris@16
|
334 ++inner_iter;
|
Chris@16
|
335 if( dominance( cur_inner_splabel->
|
Chris@16
|
336 cumulated_resource_consumption,
|
Chris@16
|
337 cur_outer_splabel->
|
Chris@16
|
338 cumulated_resource_consumption ) )
|
Chris@16
|
339 {
|
Chris@16
|
340 typename std::list<Splabel>::iterator buf = outer_iter;
|
Chris@16
|
341 ++outer_iter;
|
Chris@16
|
342 list_labels_cur_vertex.erase( buf );
|
Chris@16
|
343 b_outer_iter_erased = true;
|
Chris@101
|
344 assert (cur_outer_splabel->b_is_valid);
|
Chris@16
|
345 if( cur_outer_splabel->b_is_processed )
|
Chris@16
|
346 {
|
Chris@101
|
347 cur_outer_splabel->b_is_valid = false;
|
Chris@16
|
348 l_alloc.destroy( cur_outer_splabel.get() );
|
Chris@16
|
349 l_alloc.deallocate( cur_outer_splabel.get(), 1 );
|
Chris@16
|
350 }
|
Chris@16
|
351 else
|
Chris@16
|
352 cur_outer_splabel->b_is_dominated = true;
|
Chris@16
|
353 break;
|
Chris@16
|
354 }
|
Chris@16
|
355 }
|
Chris@16
|
356 if( !b_outer_iter_erased )
|
Chris@16
|
357 ++outer_iter;
|
Chris@16
|
358 }
|
Chris@16
|
359 if( list_labels_cur_vertex.size() > 1 )
|
Chris@101
|
360 put(vec_last_valid_positions_for_dominance, i_cur_resident_vertex,
|
Chris@101
|
361 (--(list_labels_cur_vertex.end())));
|
Chris@16
|
362 else
|
Chris@101
|
363 put(vec_last_valid_positions_for_dominance, i_cur_resident_vertex,
|
Chris@101
|
364 list_labels_cur_vertex.begin());
|
Chris@101
|
365 put(b_vec_vertex_already_checked_for_dominance,
|
Chris@101
|
366 i_cur_resident_vertex, true);
|
Chris@101
|
367 put(vec_last_valid_index_for_dominance, i_cur_resident_vertex,
|
Chris@101
|
368 list_labels_cur_vertex.size() - 1);
|
Chris@16
|
369 }
|
Chris@16
|
370 }
|
Chris@101
|
371 assert (b_all_pareto_optimal_solutions || cur_label->b_is_valid);
|
Chris@16
|
372 if( !b_all_pareto_optimal_solutions && cur_label->resident_vertex == t )
|
Chris@16
|
373 {
|
Chris@16
|
374 // the devil don't sleep
|
Chris@16
|
375 if( cur_label->b_is_dominated )
|
Chris@16
|
376 {
|
Chris@101
|
377 cur_label->b_is_valid = false;
|
Chris@16
|
378 l_alloc.destroy( cur_label.get() );
|
Chris@16
|
379 l_alloc.deallocate( cur_label.get(), 1 );
|
Chris@16
|
380 }
|
Chris@16
|
381 while( unprocessed_labels.size() )
|
Chris@16
|
382 {
|
Chris@16
|
383 Splabel l = unprocessed_labels.top();
|
Chris@101
|
384 assert (l->b_is_valid);
|
Chris@16
|
385 unprocessed_labels.pop();
|
Chris@16
|
386 // delete only dominated labels, because nondominated labels are
|
Chris@16
|
387 // deleted at the end of the function
|
Chris@16
|
388 if( l->b_is_dominated )
|
Chris@16
|
389 {
|
Chris@101
|
390 l->b_is_valid = false;
|
Chris@16
|
391 l_alloc.destroy( l.get() );
|
Chris@16
|
392 l_alloc.deallocate( l.get(), 1 );
|
Chris@16
|
393 }
|
Chris@16
|
394 }
|
Chris@16
|
395 break;
|
Chris@16
|
396 }
|
Chris@16
|
397 if( !cur_label->b_is_dominated )
|
Chris@16
|
398 {
|
Chris@16
|
399 cur_label->b_is_processed = true;
|
Chris@16
|
400 vis.on_label_not_dominated( *cur_label, g );
|
Chris@16
|
401 typename graph_traits<Graph>::vertex_descriptor cur_vertex =
|
Chris@16
|
402 cur_label->resident_vertex;
|
Chris@16
|
403 typename graph_traits<Graph>::out_edge_iterator oei, oei_end;
|
Chris@16
|
404 for( boost::tie( oei, oei_end ) = out_edges( cur_vertex, g );
|
Chris@16
|
405 oei != oei_end;
|
Chris@16
|
406 ++oei )
|
Chris@16
|
407 {
|
Chris@16
|
408 b_feasible = true;
|
Chris@16
|
409 r_c_shortest_paths_label<Graph, Resource_Container>* new_label =
|
Chris@16
|
410 l_alloc.allocate( 1 );
|
Chris@16
|
411 l_alloc.construct( new_label,
|
Chris@16
|
412 r_c_shortest_paths_label
|
Chris@16
|
413 <Graph, Resource_Container>
|
Chris@16
|
414 ( i_label_num++,
|
Chris@16
|
415 cur_label->cumulated_resource_consumption,
|
Chris@16
|
416 cur_label.get(),
|
Chris@16
|
417 *oei,
|
Chris@16
|
418 target( *oei, g ) ) );
|
Chris@16
|
419 b_feasible =
|
Chris@16
|
420 ref( g,
|
Chris@16
|
421 new_label->cumulated_resource_consumption,
|
Chris@16
|
422 new_label->p_pred_label->cumulated_resource_consumption,
|
Chris@16
|
423 new_label->pred_edge );
|
Chris@16
|
424
|
Chris@16
|
425 if( !b_feasible )
|
Chris@16
|
426 {
|
Chris@16
|
427 vis.on_label_not_feasible( *new_label, g );
|
Chris@101
|
428 new_label->b_is_valid = false;
|
Chris@16
|
429 l_alloc.destroy( new_label );
|
Chris@16
|
430 l_alloc.deallocate( new_label, 1 );
|
Chris@16
|
431 }
|
Chris@16
|
432 else
|
Chris@16
|
433 {
|
Chris@16
|
434 const r_c_shortest_paths_label<Graph, Resource_Container>&
|
Chris@16
|
435 ref_new_label = *new_label;
|
Chris@16
|
436 vis.on_label_feasible( ref_new_label, g );
|
Chris@16
|
437 Splabel new_sp_label( new_label );
|
Chris@101
|
438 vec_vertex_labels[new_sp_label->resident_vertex].
|
Chris@16
|
439 push_back( new_sp_label );
|
Chris@16
|
440 unprocessed_labels.push( new_sp_label );
|
Chris@16
|
441 }
|
Chris@16
|
442 }
|
Chris@16
|
443 }
|
Chris@16
|
444 else
|
Chris@16
|
445 {
|
Chris@101
|
446 assert (cur_label->b_is_valid);
|
Chris@16
|
447 vis.on_label_dominated( *cur_label, g );
|
Chris@101
|
448 cur_label->b_is_valid = false;
|
Chris@16
|
449 l_alloc.destroy( cur_label.get() );
|
Chris@16
|
450 l_alloc.deallocate( cur_label.get(), 1 );
|
Chris@16
|
451 }
|
Chris@16
|
452 }
|
Chris@101
|
453 std::list<Splabel> dsplabels = get(vec_vertex_labels, t);
|
Chris@16
|
454 typename std::list<Splabel>::const_iterator csi = dsplabels.begin();
|
Chris@16
|
455 typename std::list<Splabel>::const_iterator csi_end = dsplabels.end();
|
Chris@16
|
456 // if d could be reached from o
|
Chris@16
|
457 if( !dsplabels.empty() )
|
Chris@16
|
458 {
|
Chris@16
|
459 for( ; csi != csi_end; ++csi )
|
Chris@16
|
460 {
|
Chris@16
|
461 std::vector<typename graph_traits<Graph>::edge_descriptor>
|
Chris@16
|
462 cur_pareto_optimal_path;
|
Chris@16
|
463 const r_c_shortest_paths_label<Graph, Resource_Container>* p_cur_label =
|
Chris@16
|
464 (*csi).get();
|
Chris@101
|
465 assert (p_cur_label->b_is_valid);
|
Chris@16
|
466 pareto_optimal_resource_containers.
|
Chris@16
|
467 push_back( p_cur_label->cumulated_resource_consumption );
|
Chris@16
|
468 while( p_cur_label->num != 0 )
|
Chris@16
|
469 {
|
Chris@16
|
470 cur_pareto_optimal_path.push_back( p_cur_label->pred_edge );
|
Chris@16
|
471 p_cur_label = p_cur_label->p_pred_label;
|
Chris@101
|
472 assert (p_cur_label->b_is_valid);
|
Chris@16
|
473 }
|
Chris@16
|
474 pareto_optimal_solutions.push_back( cur_pareto_optimal_path );
|
Chris@16
|
475 if( !b_all_pareto_optimal_solutions )
|
Chris@16
|
476 break;
|
Chris@16
|
477 }
|
Chris@16
|
478 }
|
Chris@16
|
479
|
Chris@101
|
480 BGL_FORALL_VERTICES_T(i, g, Graph) {
|
Chris@16
|
481 const std::list<Splabel>& list_labels_cur_vertex = vec_vertex_labels[i];
|
Chris@16
|
482 csi_end = list_labels_cur_vertex.end();
|
Chris@16
|
483 for( csi = list_labels_cur_vertex.begin(); csi != csi_end; ++csi )
|
Chris@16
|
484 {
|
Chris@101
|
485 assert ((*csi)->b_is_valid);
|
Chris@101
|
486 (*csi)->b_is_valid = false;
|
Chris@16
|
487 l_alloc.destroy( (*csi).get() );
|
Chris@16
|
488 l_alloc.deallocate( (*csi).get(), 1 );
|
Chris@16
|
489 }
|
Chris@16
|
490 }
|
Chris@16
|
491 } // r_c_shortest_paths_dispatch
|
Chris@16
|
492
|
Chris@16
|
493 } // detail
|
Chris@16
|
494
|
Chris@16
|
495 // default_r_c_shortest_paths_visitor struct
|
Chris@16
|
496 struct default_r_c_shortest_paths_visitor
|
Chris@16
|
497 {
|
Chris@16
|
498 template<class Label, class Graph>
|
Chris@16
|
499 void on_label_popped( const Label&, const Graph& ) {}
|
Chris@16
|
500 template<class Label, class Graph>
|
Chris@16
|
501 void on_label_feasible( const Label&, const Graph& ) {}
|
Chris@16
|
502 template<class Label, class Graph>
|
Chris@16
|
503 void on_label_not_feasible( const Label&, const Graph& ) {}
|
Chris@16
|
504 template<class Label, class Graph>
|
Chris@16
|
505 void on_label_dominated( const Label&, const Graph& ) {}
|
Chris@16
|
506 template<class Label, class Graph>
|
Chris@16
|
507 void on_label_not_dominated( const Label&, const Graph& ) {}
|
Chris@16
|
508 template<class Queue, class Graph>
|
Chris@16
|
509 bool on_enter_loop(const Queue& queue, const Graph& graph) {return true;}
|
Chris@16
|
510 }; // default_r_c_shortest_paths_visitor
|
Chris@16
|
511
|
Chris@16
|
512
|
Chris@16
|
513 // default_r_c_shortest_paths_allocator
|
Chris@16
|
514 typedef
|
Chris@16
|
515 std::allocator<int> default_r_c_shortest_paths_allocator;
|
Chris@16
|
516 // default_r_c_shortest_paths_allocator
|
Chris@16
|
517
|
Chris@16
|
518
|
Chris@16
|
519 // r_c_shortest_paths functions (handle/interface)
|
Chris@16
|
520 // first overload:
|
Chris@16
|
521 // - return all pareto-optimal solutions
|
Chris@16
|
522 // - specify Label_Allocator and Visitor arguments
|
Chris@16
|
523 template<class Graph,
|
Chris@16
|
524 class VertexIndexMap,
|
Chris@16
|
525 class EdgeIndexMap,
|
Chris@16
|
526 class Resource_Container,
|
Chris@16
|
527 class Resource_Extension_Function,
|
Chris@16
|
528 class Dominance_Function,
|
Chris@16
|
529 class Label_Allocator,
|
Chris@16
|
530 class Visitor>
|
Chris@16
|
531 void r_c_shortest_paths
|
Chris@16
|
532 ( const Graph& g,
|
Chris@16
|
533 const VertexIndexMap& vertex_index_map,
|
Chris@16
|
534 const EdgeIndexMap& edge_index_map,
|
Chris@16
|
535 typename graph_traits<Graph>::vertex_descriptor s,
|
Chris@16
|
536 typename graph_traits<Graph>::vertex_descriptor t,
|
Chris@16
|
537 // each inner vector corresponds to a pareto-optimal path
|
Chris@16
|
538 std::vector<std::vector<typename graph_traits<Graph>::edge_descriptor> >&
|
Chris@16
|
539 pareto_optimal_solutions,
|
Chris@16
|
540 std::vector<Resource_Container>& pareto_optimal_resource_containers,
|
Chris@16
|
541 // to initialize the first label/resource container
|
Chris@16
|
542 // and to carry the type information
|
Chris@16
|
543 const Resource_Container& rc,
|
Chris@16
|
544 const Resource_Extension_Function& ref,
|
Chris@16
|
545 const Dominance_Function& dominance,
|
Chris@16
|
546 // to specify the memory management strategy for the labels
|
Chris@16
|
547 Label_Allocator la,
|
Chris@16
|
548 Visitor vis )
|
Chris@16
|
549 {
|
Chris@16
|
550 r_c_shortest_paths_dispatch( g,
|
Chris@16
|
551 vertex_index_map,
|
Chris@16
|
552 edge_index_map,
|
Chris@16
|
553 s,
|
Chris@16
|
554 t,
|
Chris@16
|
555 pareto_optimal_solutions,
|
Chris@16
|
556 pareto_optimal_resource_containers,
|
Chris@16
|
557 true,
|
Chris@16
|
558 rc,
|
Chris@16
|
559 ref,
|
Chris@16
|
560 dominance,
|
Chris@16
|
561 la,
|
Chris@16
|
562 vis );
|
Chris@16
|
563 }
|
Chris@16
|
564
|
Chris@16
|
565 // second overload:
|
Chris@16
|
566 // - return only one pareto-optimal solution
|
Chris@16
|
567 // - specify Label_Allocator and Visitor arguments
|
Chris@16
|
568 template<class Graph,
|
Chris@16
|
569 class VertexIndexMap,
|
Chris@16
|
570 class EdgeIndexMap,
|
Chris@16
|
571 class Resource_Container,
|
Chris@16
|
572 class Resource_Extension_Function,
|
Chris@16
|
573 class Dominance_Function,
|
Chris@16
|
574 class Label_Allocator,
|
Chris@16
|
575 class Visitor>
|
Chris@16
|
576 void r_c_shortest_paths
|
Chris@16
|
577 ( const Graph& g,
|
Chris@16
|
578 const VertexIndexMap& vertex_index_map,
|
Chris@16
|
579 const EdgeIndexMap& edge_index_map,
|
Chris@16
|
580 typename graph_traits<Graph>::vertex_descriptor s,
|
Chris@16
|
581 typename graph_traits<Graph>::vertex_descriptor t,
|
Chris@16
|
582 std::vector<typename graph_traits<Graph>::edge_descriptor>&
|
Chris@16
|
583 pareto_optimal_solution,
|
Chris@16
|
584 Resource_Container& pareto_optimal_resource_container,
|
Chris@16
|
585 // to initialize the first label/resource container
|
Chris@16
|
586 // and to carry the type information
|
Chris@16
|
587 const Resource_Container& rc,
|
Chris@16
|
588 const Resource_Extension_Function& ref,
|
Chris@16
|
589 const Dominance_Function& dominance,
|
Chris@16
|
590 // to specify the memory management strategy for the labels
|
Chris@16
|
591 Label_Allocator la,
|
Chris@16
|
592 Visitor vis )
|
Chris@16
|
593 {
|
Chris@16
|
594 // each inner vector corresponds to a pareto-optimal path
|
Chris@16
|
595 std::vector<std::vector<typename graph_traits<Graph>::edge_descriptor> >
|
Chris@16
|
596 pareto_optimal_solutions;
|
Chris@16
|
597 std::vector<Resource_Container> pareto_optimal_resource_containers;
|
Chris@16
|
598 r_c_shortest_paths_dispatch( g,
|
Chris@16
|
599 vertex_index_map,
|
Chris@16
|
600 edge_index_map,
|
Chris@16
|
601 s,
|
Chris@16
|
602 t,
|
Chris@16
|
603 pareto_optimal_solutions,
|
Chris@16
|
604 pareto_optimal_resource_containers,
|
Chris@16
|
605 false,
|
Chris@16
|
606 rc,
|
Chris@16
|
607 ref,
|
Chris@16
|
608 dominance,
|
Chris@16
|
609 la,
|
Chris@16
|
610 vis );
|
Chris@16
|
611 if (!pareto_optimal_solutions.empty()) {
|
Chris@16
|
612 pareto_optimal_solution = pareto_optimal_solutions[0];
|
Chris@16
|
613 pareto_optimal_resource_container = pareto_optimal_resource_containers[0];
|
Chris@16
|
614 }
|
Chris@16
|
615 }
|
Chris@16
|
616
|
Chris@16
|
617 // third overload:
|
Chris@16
|
618 // - return all pareto-optimal solutions
|
Chris@16
|
619 // - use default Label_Allocator and Visitor
|
Chris@16
|
620 template<class Graph,
|
Chris@16
|
621 class VertexIndexMap,
|
Chris@16
|
622 class EdgeIndexMap,
|
Chris@16
|
623 class Resource_Container,
|
Chris@16
|
624 class Resource_Extension_Function,
|
Chris@16
|
625 class Dominance_Function>
|
Chris@16
|
626 void r_c_shortest_paths
|
Chris@16
|
627 ( const Graph& g,
|
Chris@16
|
628 const VertexIndexMap& vertex_index_map,
|
Chris@16
|
629 const EdgeIndexMap& edge_index_map,
|
Chris@16
|
630 typename graph_traits<Graph>::vertex_descriptor s,
|
Chris@16
|
631 typename graph_traits<Graph>::vertex_descriptor t,
|
Chris@16
|
632 // each inner vector corresponds to a pareto-optimal path
|
Chris@16
|
633 std::vector<std::vector<typename graph_traits<Graph>::edge_descriptor> >&
|
Chris@16
|
634 pareto_optimal_solutions,
|
Chris@16
|
635 std::vector<Resource_Container>& pareto_optimal_resource_containers,
|
Chris@16
|
636 // to initialize the first label/resource container
|
Chris@16
|
637 // and to carry the type information
|
Chris@16
|
638 const Resource_Container& rc,
|
Chris@16
|
639 const Resource_Extension_Function& ref,
|
Chris@16
|
640 const Dominance_Function& dominance )
|
Chris@16
|
641 {
|
Chris@16
|
642 r_c_shortest_paths_dispatch( g,
|
Chris@16
|
643 vertex_index_map,
|
Chris@16
|
644 edge_index_map,
|
Chris@16
|
645 s,
|
Chris@16
|
646 t,
|
Chris@16
|
647 pareto_optimal_solutions,
|
Chris@16
|
648 pareto_optimal_resource_containers,
|
Chris@16
|
649 true,
|
Chris@16
|
650 rc,
|
Chris@16
|
651 ref,
|
Chris@16
|
652 dominance,
|
Chris@16
|
653 default_r_c_shortest_paths_allocator(),
|
Chris@16
|
654 default_r_c_shortest_paths_visitor() );
|
Chris@16
|
655 }
|
Chris@16
|
656
|
Chris@16
|
657 // fourth overload:
|
Chris@16
|
658 // - return only one pareto-optimal solution
|
Chris@16
|
659 // - use default Label_Allocator and Visitor
|
Chris@16
|
660 template<class Graph,
|
Chris@16
|
661 class VertexIndexMap,
|
Chris@16
|
662 class EdgeIndexMap,
|
Chris@16
|
663 class Resource_Container,
|
Chris@16
|
664 class Resource_Extension_Function,
|
Chris@16
|
665 class Dominance_Function>
|
Chris@16
|
666 void r_c_shortest_paths
|
Chris@16
|
667 ( const Graph& g,
|
Chris@16
|
668 const VertexIndexMap& vertex_index_map,
|
Chris@16
|
669 const EdgeIndexMap& edge_index_map,
|
Chris@16
|
670 typename graph_traits<Graph>::vertex_descriptor s,
|
Chris@16
|
671 typename graph_traits<Graph>::vertex_descriptor t,
|
Chris@16
|
672 std::vector<typename graph_traits<Graph>::edge_descriptor>&
|
Chris@16
|
673 pareto_optimal_solution,
|
Chris@16
|
674 Resource_Container& pareto_optimal_resource_container,
|
Chris@16
|
675 // to initialize the first label/resource container
|
Chris@16
|
676 // and to carry the type information
|
Chris@16
|
677 const Resource_Container& rc,
|
Chris@16
|
678 const Resource_Extension_Function& ref,
|
Chris@16
|
679 const Dominance_Function& dominance )
|
Chris@16
|
680 {
|
Chris@16
|
681 // each inner vector corresponds to a pareto-optimal path
|
Chris@16
|
682 std::vector<std::vector<typename graph_traits<Graph>::edge_descriptor> >
|
Chris@16
|
683 pareto_optimal_solutions;
|
Chris@16
|
684 std::vector<Resource_Container> pareto_optimal_resource_containers;
|
Chris@16
|
685 r_c_shortest_paths_dispatch( g,
|
Chris@16
|
686 vertex_index_map,
|
Chris@16
|
687 edge_index_map,
|
Chris@16
|
688 s,
|
Chris@16
|
689 t,
|
Chris@16
|
690 pareto_optimal_solutions,
|
Chris@16
|
691 pareto_optimal_resource_containers,
|
Chris@16
|
692 false,
|
Chris@16
|
693 rc,
|
Chris@16
|
694 ref,
|
Chris@16
|
695 dominance,
|
Chris@16
|
696 default_r_c_shortest_paths_allocator(),
|
Chris@16
|
697 default_r_c_shortest_paths_visitor() );
|
Chris@16
|
698 if (!pareto_optimal_solutions.empty()) {
|
Chris@16
|
699 pareto_optimal_solution = pareto_optimal_solutions[0];
|
Chris@16
|
700 pareto_optimal_resource_container = pareto_optimal_resource_containers[0];
|
Chris@16
|
701 }
|
Chris@16
|
702 }
|
Chris@16
|
703 // r_c_shortest_paths
|
Chris@16
|
704
|
Chris@16
|
705
|
Chris@16
|
706 // check_r_c_path function
|
Chris@16
|
707 template<class Graph,
|
Chris@16
|
708 class Resource_Container,
|
Chris@16
|
709 class Resource_Extension_Function>
|
Chris@16
|
710 void check_r_c_path( const Graph& g,
|
Chris@16
|
711 const std::vector
|
Chris@16
|
712 <typename graph_traits
|
Chris@16
|
713 <Graph>::edge_descriptor>& ed_vec_path,
|
Chris@16
|
714 const Resource_Container& initial_resource_levels,
|
Chris@16
|
715 // if true, computed accumulated final resource levels must
|
Chris@16
|
716 // be equal to desired_final_resource_levels
|
Chris@16
|
717 // if false, computed accumulated final resource levels must
|
Chris@16
|
718 // be less than or equal to desired_final_resource_levels
|
Chris@16
|
719 bool b_result_must_be_equal_to_desired_final_resource_levels,
|
Chris@16
|
720 const Resource_Container& desired_final_resource_levels,
|
Chris@16
|
721 Resource_Container& actual_final_resource_levels,
|
Chris@16
|
722 const Resource_Extension_Function& ref,
|
Chris@16
|
723 bool& b_is_a_path_at_all,
|
Chris@16
|
724 bool& b_feasible,
|
Chris@16
|
725 bool& b_correctly_extended,
|
Chris@16
|
726 typename graph_traits<Graph>::edge_descriptor&
|
Chris@16
|
727 ed_last_extended_arc )
|
Chris@16
|
728 {
|
Chris@16
|
729 size_t i_size_ed_vec_path = ed_vec_path.size();
|
Chris@16
|
730 std::vector<typename graph_traits<Graph>::edge_descriptor> buf_path;
|
Chris@16
|
731 if( i_size_ed_vec_path == 0 )
|
Chris@16
|
732 b_feasible = true;
|
Chris@16
|
733 else
|
Chris@16
|
734 {
|
Chris@16
|
735 if( i_size_ed_vec_path == 1
|
Chris@16
|
736 || target( ed_vec_path[0], g ) == source( ed_vec_path[1], g ) )
|
Chris@16
|
737 buf_path = ed_vec_path;
|
Chris@16
|
738 else
|
Chris@16
|
739 for( size_t i = i_size_ed_vec_path ; i > 0; --i )
|
Chris@16
|
740 buf_path.push_back( ed_vec_path[i - 1] );
|
Chris@16
|
741 for( size_t i = 0; i < i_size_ed_vec_path - 1; ++i )
|
Chris@16
|
742 {
|
Chris@16
|
743 if( target( buf_path[i], g ) != source( buf_path[i + 1], g ) )
|
Chris@16
|
744 {
|
Chris@16
|
745 b_is_a_path_at_all = false;
|
Chris@16
|
746 b_feasible = false;
|
Chris@16
|
747 b_correctly_extended = false;
|
Chris@16
|
748 return;
|
Chris@16
|
749 }
|
Chris@16
|
750 }
|
Chris@16
|
751 }
|
Chris@16
|
752 b_is_a_path_at_all = true;
|
Chris@16
|
753 b_feasible = true;
|
Chris@16
|
754 b_correctly_extended = false;
|
Chris@16
|
755 Resource_Container current_resource_levels = initial_resource_levels;
|
Chris@16
|
756 actual_final_resource_levels = current_resource_levels;
|
Chris@16
|
757 for( size_t i = 0; i < i_size_ed_vec_path; ++i )
|
Chris@16
|
758 {
|
Chris@16
|
759 ed_last_extended_arc = buf_path[i];
|
Chris@16
|
760 b_feasible = ref( g,
|
Chris@16
|
761 actual_final_resource_levels,
|
Chris@16
|
762 current_resource_levels,
|
Chris@16
|
763 buf_path[i] );
|
Chris@16
|
764 current_resource_levels = actual_final_resource_levels;
|
Chris@16
|
765 if( !b_feasible )
|
Chris@16
|
766 return;
|
Chris@16
|
767 }
|
Chris@16
|
768 if( b_result_must_be_equal_to_desired_final_resource_levels )
|
Chris@16
|
769 b_correctly_extended =
|
Chris@16
|
770 actual_final_resource_levels == desired_final_resource_levels ?
|
Chris@16
|
771 true : false;
|
Chris@16
|
772 else
|
Chris@16
|
773 {
|
Chris@16
|
774 if( actual_final_resource_levels < desired_final_resource_levels
|
Chris@16
|
775 || actual_final_resource_levels == desired_final_resource_levels )
|
Chris@16
|
776 b_correctly_extended = true;
|
Chris@16
|
777 }
|
Chris@16
|
778 } // check_path
|
Chris@16
|
779
|
Chris@16
|
780 } // namespace
|
Chris@16
|
781
|
Chris@16
|
782 #endif // BOOST_GRAPH_R_C_SHORTEST_PATHS_HPP
|