r_c_shortest_paths_example.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  1. // Copyright Michael Drexl 2005, 2006.
  2. // Distributed under the Boost Software License, Version 1.0.
  3. // (See accompanying file LICENSE_1_0.txt or copy at
  4. // http://boost.org/LICENSE_1_0.txt)
  5. // Example use of the resource-constrained shortest paths algorithm.
  6. #include <boost/config.hpp>
  7. #ifdef BOOST_MSVC
  8. # pragma warning(disable: 4267)
  9. #endif
  10. #include <boost/graph/adjacency_list.hpp>
  11. #include <boost/graph/r_c_shortest_paths.hpp>
  12. #include <iostream>
  13. using namespace boost;
  14. struct SPPRC_Example_Graph_Vert_Prop
  15. {
  16. SPPRC_Example_Graph_Vert_Prop( int n = 0, int e = 0, int l = 0 )
  17. : num( n ), eat( e ), lat( l ) {}
  18. int num;
  19. // earliest arrival time
  20. int eat;
  21. // latest arrival time
  22. int lat;
  23. };
  24. struct SPPRC_Example_Graph_Arc_Prop
  25. {
  26. SPPRC_Example_Graph_Arc_Prop( int n = 0, int c = 0, int t = 0 )
  27. : num( n ), cost( c ), time( t ) {}
  28. int num;
  29. // traversal cost
  30. int cost;
  31. // traversal time
  32. int time;
  33. };
  34. typedef adjacency_list<vecS,
  35. vecS,
  36. directedS,
  37. SPPRC_Example_Graph_Vert_Prop,
  38. SPPRC_Example_Graph_Arc_Prop>
  39. SPPRC_Example_Graph;
  40. // data structures for spp without resource constraints:
  41. // ResourceContainer model
  42. struct spp_no_rc_res_cont
  43. {
  44. spp_no_rc_res_cont( int c = 0 ) : cost( c ) {};
  45. spp_no_rc_res_cont& operator=( const spp_no_rc_res_cont& other )
  46. {
  47. if( this == &other )
  48. return *this;
  49. this->~spp_no_rc_res_cont();
  50. new( this ) spp_no_rc_res_cont( other );
  51. return *this;
  52. }
  53. int cost;
  54. };
  55. bool operator==( const spp_no_rc_res_cont& res_cont_1,
  56. const spp_no_rc_res_cont& res_cont_2 )
  57. {
  58. return ( res_cont_1.cost == res_cont_2.cost );
  59. }
  60. bool operator<( const spp_no_rc_res_cont& res_cont_1,
  61. const spp_no_rc_res_cont& res_cont_2 )
  62. {
  63. return ( res_cont_1.cost < res_cont_2.cost );
  64. }
  65. // ResourceExtensionFunction model
  66. class ref_no_res_cont
  67. {
  68. public:
  69. inline bool operator()( const SPPRC_Example_Graph& g,
  70. spp_no_rc_res_cont& new_cont,
  71. const spp_no_rc_res_cont& old_cont,
  72. graph_traits
  73. <SPPRC_Example_Graph>::edge_descriptor ed ) const
  74. {
  75. new_cont.cost = old_cont.cost + g[ed].cost;
  76. return true;
  77. }
  78. };
  79. // DominanceFunction model
  80. class dominance_no_res_cont
  81. {
  82. public:
  83. inline bool operator()( const spp_no_rc_res_cont& res_cont_1,
  84. const spp_no_rc_res_cont& res_cont_2 ) const
  85. {
  86. // must be "<=" here!!!
  87. // must NOT be "<"!!!
  88. return res_cont_1.cost <= res_cont_2.cost;
  89. // this is not a contradiction to the documentation
  90. // the documentation says:
  91. // "A label $l_1$ dominates a label $l_2$ if and only if both are resident
  92. // at the same vertex, and if, for each resource, the resource consumption
  93. // of $l_1$ is less than or equal to the resource consumption of $l_2$,
  94. // and if there is at least one resource where $l_1$ has a lower resource
  95. // consumption than $l_2$."
  96. // one can think of a new label with a resource consumption equal to that
  97. // of an old label as being dominated by that old label, because the new
  98. // one will have a higher number and is created at a later point in time,
  99. // so one can implicitly use the number or the creation time as a resource
  100. // for tie-breaking
  101. }
  102. };
  103. // end data structures for spp without resource constraints:
  104. // data structures for shortest path problem with time windows (spptw)
  105. // ResourceContainer model
  106. struct spp_spptw_res_cont
  107. {
  108. spp_spptw_res_cont( int c = 0, int t = 0 ) : cost( c ), time( t ) {}
  109. spp_spptw_res_cont& operator=( const spp_spptw_res_cont& other )
  110. {
  111. if( this == &other )
  112. return *this;
  113. this->~spp_spptw_res_cont();
  114. new( this ) spp_spptw_res_cont( other );
  115. return *this;
  116. }
  117. int cost;
  118. int time;
  119. };
  120. bool operator==( const spp_spptw_res_cont& res_cont_1,
  121. const spp_spptw_res_cont& res_cont_2 )
  122. {
  123. return ( res_cont_1.cost == res_cont_2.cost
  124. && res_cont_1.time == res_cont_2.time );
  125. }
  126. bool operator<( const spp_spptw_res_cont& res_cont_1,
  127. const spp_spptw_res_cont& res_cont_2 )
  128. {
  129. if( res_cont_1.cost > res_cont_2.cost )
  130. return false;
  131. if( res_cont_1.cost == res_cont_2.cost )
  132. return res_cont_1.time < res_cont_2.time;
  133. return true;
  134. }
  135. // ResourceExtensionFunction model
  136. class ref_spptw
  137. {
  138. public:
  139. inline bool operator()( const SPPRC_Example_Graph& g,
  140. spp_spptw_res_cont& new_cont,
  141. const spp_spptw_res_cont& old_cont,
  142. graph_traits
  143. <SPPRC_Example_Graph>::edge_descriptor ed ) const
  144. {
  145. const SPPRC_Example_Graph_Arc_Prop& arc_prop =
  146. get( edge_bundle, g )[ed];
  147. const SPPRC_Example_Graph_Vert_Prop& vert_prop =
  148. get( vertex_bundle, g )[target( ed, g )];
  149. new_cont.cost = old_cont.cost + arc_prop.cost;
  150. int& i_time = new_cont.time;
  151. i_time = old_cont.time + arc_prop.time;
  152. i_time < vert_prop.eat ? i_time = vert_prop.eat : 0;
  153. return i_time <= vert_prop.lat ? true : false;
  154. }
  155. };
  156. // DominanceFunction model
  157. class dominance_spptw
  158. {
  159. public:
  160. inline bool operator()( const spp_spptw_res_cont& res_cont_1,
  161. const spp_spptw_res_cont& res_cont_2 ) const
  162. {
  163. // must be "<=" here!!!
  164. // must NOT be "<"!!!
  165. return res_cont_1.cost <= res_cont_2.cost
  166. && res_cont_1.time <= res_cont_2.time;
  167. // this is not a contradiction to the documentation
  168. // the documentation says:
  169. // "A label $l_1$ dominates a label $l_2$ if and only if both are resident
  170. // at the same vertex, and if, for each resource, the resource consumption
  171. // of $l_1$ is less than or equal to the resource consumption of $l_2$,
  172. // and if there is at least one resource where $l_1$ has a lower resource
  173. // consumption than $l_2$."
  174. // one can think of a new label with a resource consumption equal to that
  175. // of an old label as being dominated by that old label, because the new
  176. // one will have a higher number and is created at a later point in time,
  177. // so one can implicitly use the number or the creation time as a resource
  178. // for tie-breaking
  179. }
  180. };
  181. // end data structures for shortest path problem with time windows (spptw)
  182. // example graph structure and cost from
  183. // http://www.boost.org/libs/graph/example/dijkstra-example.cpp
  184. enum nodes { A, B, C, D, E };
  185. char name[] = "ABCDE";
  186. int main()
  187. {
  188. SPPRC_Example_Graph g;
  189. add_vertex( SPPRC_Example_Graph_Vert_Prop( A, 0, 0 ), g );
  190. add_vertex( SPPRC_Example_Graph_Vert_Prop( B, 5, 20 ), g );
  191. add_vertex( SPPRC_Example_Graph_Vert_Prop( C, 6, 10 ), g );
  192. add_vertex( SPPRC_Example_Graph_Vert_Prop( D, 3, 12 ), g );
  193. add_vertex( SPPRC_Example_Graph_Vert_Prop( E, 0, 100 ), g );
  194. add_edge( A, C, SPPRC_Example_Graph_Arc_Prop( 0, 1, 5 ), g );
  195. add_edge( B, B, SPPRC_Example_Graph_Arc_Prop( 1, 2, 5 ), g );
  196. add_edge( B, D, SPPRC_Example_Graph_Arc_Prop( 2, 1, 2 ), g );
  197. add_edge( B, E, SPPRC_Example_Graph_Arc_Prop( 3, 2, 7 ), g );
  198. add_edge( C, B, SPPRC_Example_Graph_Arc_Prop( 4, 7, 3 ), g );
  199. add_edge( C, D, SPPRC_Example_Graph_Arc_Prop( 5, 3, 8 ), g );
  200. add_edge( D, E, SPPRC_Example_Graph_Arc_Prop( 6, 1, 3 ), g );
  201. add_edge( E, A, SPPRC_Example_Graph_Arc_Prop( 7, 1, 5 ), g );
  202. add_edge( E, B, SPPRC_Example_Graph_Arc_Prop( 8, 1, 4 ), g );
  203. // the unique shortest path from A to E in the dijkstra-example.cpp is
  204. // A -> C -> D -> E
  205. // its length is 5
  206. // the following code also yields this result
  207. // with the above time windows, this path is infeasible
  208. // now, there are two shortest paths that are also feasible with respect to
  209. // the vertex time windows:
  210. // A -> C -> B -> D -> E and
  211. // A -> C -> B -> E
  212. // however, the latter has a longer total travel time and is therefore not
  213. // pareto-optimal, i.e., it is dominated by the former path
  214. // therefore, the code below returns only the former path
  215. // spp without resource constraints
  216. graph_traits<SPPRC_Example_Graph>::vertex_descriptor s = A;
  217. graph_traits<SPPRC_Example_Graph>::vertex_descriptor t = E;
  218. std::vector
  219. <std::vector
  220. <graph_traits<SPPRC_Example_Graph>::edge_descriptor> >
  221. opt_solutions;
  222. std::vector<spp_no_rc_res_cont> pareto_opt_rcs_no_rc;
  223. r_c_shortest_paths
  224. ( g,
  225. get( &SPPRC_Example_Graph_Vert_Prop::num, g ),
  226. get( &SPPRC_Example_Graph_Arc_Prop::num, g ),
  227. s,
  228. t,
  229. opt_solutions,
  230. pareto_opt_rcs_no_rc,
  231. spp_no_rc_res_cont( 0 ),
  232. ref_no_res_cont(),
  233. dominance_no_res_cont(),
  234. std::allocator
  235. <r_c_shortest_paths_label
  236. <SPPRC_Example_Graph, spp_no_rc_res_cont> >(),
  237. default_r_c_shortest_paths_visitor() );
  238. std::cout << "SPP without resource constraints:" << std::endl;
  239. std::cout << "Number of optimal solutions: ";
  240. std::cout << static_cast<int>( opt_solutions.size() ) << std::endl;
  241. for( int i = 0; i < static_cast<int>( opt_solutions.size() ); ++i )
  242. {
  243. std::cout << "The " << i << "th shortest path from A to E is: ";
  244. std::cout << std::endl;
  245. for( int j = static_cast<int>( opt_solutions[i].size() ) - 1; j >= 0; --j )
  246. std::cout << name[source( opt_solutions[i][j], g )] << std::endl;
  247. std::cout << "E" << std::endl;
  248. std::cout << "Length: " << pareto_opt_rcs_no_rc[i].cost << std::endl;
  249. }
  250. std::cout << std::endl;
  251. // spptw
  252. std::vector
  253. <std::vector
  254. <graph_traits<SPPRC_Example_Graph>::edge_descriptor> >
  255. opt_solutions_spptw;
  256. std::vector<spp_spptw_res_cont> pareto_opt_rcs_spptw;
  257. r_c_shortest_paths
  258. ( g,
  259. get( &SPPRC_Example_Graph_Vert_Prop::num, g ),
  260. get( &SPPRC_Example_Graph_Arc_Prop::num, g ),
  261. s,
  262. t,
  263. opt_solutions_spptw,
  264. pareto_opt_rcs_spptw,
  265. spp_spptw_res_cont( 0, 0 ),
  266. ref_spptw(),
  267. dominance_spptw(),
  268. std::allocator
  269. <r_c_shortest_paths_label
  270. <SPPRC_Example_Graph, spp_spptw_res_cont> >(),
  271. default_r_c_shortest_paths_visitor() );
  272. std::cout << "SPP with time windows:" << std::endl;
  273. std::cout << "Number of optimal solutions: ";
  274. std::cout << static_cast<int>( opt_solutions.size() ) << std::endl;
  275. for( int i = 0; i < static_cast<int>( opt_solutions.size() ); ++i )
  276. {
  277. std::cout << "The " << i << "th shortest path from A to E is: ";
  278. std::cout << std::endl;
  279. for( int j = static_cast<int>( opt_solutions_spptw[i].size() ) - 1;
  280. j >= 0;
  281. --j )
  282. std::cout << name[source( opt_solutions_spptw[i][j], g )] << std::endl;
  283. std::cout << "E" << std::endl;
  284. std::cout << "Length: " << pareto_opt_rcs_spptw[i].cost << std::endl;
  285. std::cout << "Time: " << pareto_opt_rcs_spptw[i].time << std::endl;
  286. }
  287. // utility function check_r_c_path example
  288. std::cout << std::endl;
  289. bool b_is_a_path_at_all = false;
  290. bool b_feasible = false;
  291. bool b_correctly_extended = false;
  292. spp_spptw_res_cont actual_final_resource_levels( 0, 0 );
  293. graph_traits<SPPRC_Example_Graph>::edge_descriptor ed_last_extended_arc;
  294. check_r_c_path( g,
  295. opt_solutions_spptw[0],
  296. spp_spptw_res_cont( 0, 0 ),
  297. true,
  298. pareto_opt_rcs_spptw[0],
  299. actual_final_resource_levels,
  300. ref_spptw(),
  301. b_is_a_path_at_all,
  302. b_feasible,
  303. b_correctly_extended,
  304. ed_last_extended_arc );
  305. if( !b_is_a_path_at_all )
  306. std::cout << "Not a path." << std::endl;
  307. if( !b_feasible )
  308. std::cout << "Not a feasible path." << std::endl;
  309. if( !b_correctly_extended )
  310. std::cout << "Not correctly extended." << std::endl;
  311. if( b_is_a_path_at_all && b_feasible && b_correctly_extended )
  312. {
  313. std::cout << "Actual final resource levels:" << std::endl;
  314. std::cout << "Length: " << actual_final_resource_levels.cost << std::endl;
  315. std::cout << "Time: " << actual_final_resource_levels.time << std::endl;
  316. std::cout << "OK." << std::endl;
  317. }
  318. return 0;
  319. }