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