• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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