From fc60b865a9b18fdde22dbe77cb1fc6555ec901cc Mon Sep 17 00:00:00 2001 From: Andrea Cassioli Date: Sun, 19 Jul 2026 17:38:17 +0200 Subject: [PATCH 1/3] introduce new functions --- include/boost/graph/r_c_shortest_paths.hpp | 134 ++++++++++++++++++--- 1 file changed, 119 insertions(+), 15 deletions(-) diff --git a/include/boost/graph/r_c_shortest_paths.hpp b/include/boost/graph/r_c_shortest_paths.hpp index 12edb43dc..a32882cf9 100644 --- a/include/boost/graph/r_c_shortest_paths.hpp +++ b/include/boost/graph/r_c_shortest_paths.hpp @@ -163,12 +163,11 @@ namespace detail { // r_c_shortest_paths_dispatch function (body/implementation) - template < class Graph, class VertexIndexMap, class EdgeIndexMap, + template < class Graph, class VertexIndexMap, class Resource_Container, class Resource_Extension_Function, class Dominance_Function, class Label_Allocator, class Visitor > void r_c_shortest_paths_dispatch(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, // each inner vector corresponds to a pareto-optimal path @@ -527,16 +526,18 @@ struct default_r_c_shortest_paths_visitor // default_r_c_shortest_paths_allocator typedef std::allocator< int > default_r_c_shortest_paths_allocator; // default_r_c_shortest_paths_allocator +// ---------------------------- New set of overloads -// r_c_shortest_paths functions (handle/interface) + + +// New r_c_shortest_paths functions (handle/interface) // first overload: // - return all pareto-optimal solutions // - specify Label_Allocator and Visitor arguments -template < class Graph, class VertexIndexMap, class EdgeIndexMap, +template < class Graph, class VertexIndexMap, class Resource_Container, class Resource_Extension_Function, class Dominance_Function, class Label_Allocator, class Visitor > void 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, // each inner vector corresponds to a pareto-optimal path @@ -551,19 +552,19 @@ void r_c_shortest_paths(const Graph& g, const VertexIndexMap& vertex_index_map, // to specify the memory management strategy for the labels Label_Allocator la, Visitor vis) { - r_c_shortest_paths_dispatch(g, vertex_index_map, edge_index_map, s, t, + r_c_shortest_paths_dispatch(g, vertex_index_map, s, t, pareto_optimal_solutions, pareto_optimal_resource_containers, true, rc, ref, dominance, la, vis); } + // second overload: // - return only one pareto-optimal solution // - specify Label_Allocator and Visitor arguments -template < class Graph, class VertexIndexMap, class EdgeIndexMap, +template < class Graph, class VertexIndexMap, class Resource_Container, class Resource_Extension_Function, class Dominance_Function, class Label_Allocator, class Visitor > void 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 >& @@ -581,7 +582,7 @@ void r_c_shortest_paths(const Graph& g, const VertexIndexMap& vertex_index_map, std::vector< typename graph_traits< Graph >::edge_descriptor > > pareto_optimal_solutions; std::vector< Resource_Container > pareto_optimal_resource_containers; - r_c_shortest_paths_dispatch(g, vertex_index_map, edge_index_map, s, t, + r_c_shortest_paths_dispatch(g, vertex_index_map, s, t, pareto_optimal_solutions, pareto_optimal_resource_containers, false, rc, ref, dominance, la, vis); if (!pareto_optimal_solutions.empty()) @@ -595,11 +596,10 @@ void r_c_shortest_paths(const Graph& g, const VertexIndexMap& vertex_index_map, // third overload: // - return all pareto-optimal solutions // - use default Label_Allocator and Visitor -template < class Graph, class VertexIndexMap, class EdgeIndexMap, +template < class Graph, class VertexIndexMap, class Resource_Container, class Resource_Extension_Function, class Dominance_Function > void 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, // each inner vector corresponds to a pareto-optimal path @@ -612,20 +612,20 @@ void r_c_shortest_paths(const Graph& g, const VertexIndexMap& vertex_index_map, const Resource_Container& rc, const Resource_Extension_Function& ref, const Dominance_Function& dominance) { - r_c_shortest_paths_dispatch(g, vertex_index_map, edge_index_map, s, t, + r_c_shortest_paths_dispatch(g, vertex_index_map, s, t, pareto_optimal_solutions, pareto_optimal_resource_containers, true, rc, ref, dominance, default_r_c_shortest_paths_allocator(), default_r_c_shortest_paths_visitor()); } + // fourth overload: // - return only one pareto-optimal solution // - use default Label_Allocator and Visitor -template < class Graph, class VertexIndexMap, class EdgeIndexMap, +template < class Graph, class VertexIndexMap, class Resource_Container, class Resource_Extension_Function, class Dominance_Function > void 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 >& @@ -641,7 +641,7 @@ void r_c_shortest_paths(const Graph& g, const VertexIndexMap& vertex_index_map, std::vector< typename graph_traits< Graph >::edge_descriptor > > pareto_optimal_solutions; std::vector< Resource_Container > pareto_optimal_resource_containers; - r_c_shortest_paths_dispatch(g, vertex_index_map, edge_index_map, s, t, + r_c_shortest_paths_dispatch(g, vertex_index_map, s, t, pareto_optimal_solutions, pareto_optimal_resource_containers, false, rc, ref, dominance, default_r_c_shortest_paths_allocator(), default_r_c_shortest_paths_visitor()); @@ -652,8 +652,112 @@ void r_c_shortest_paths(const Graph& g, const VertexIndexMap& vertex_index_map, = pareto_optimal_resource_containers[0]; } } + +// ---------------------------- Old r_c_shortest_paths functions (handle/interface) +// These functions are kept durign the deprecation cycle, but their logic falls back to the new functions + + +// first overload: +// - return all pareto-optimal solutions +// - specify Label_Allocator and Visitor arguments +template < class Graph, class VertexIndexMap, class EdgeIndexMap, + class Resource_Container, class Resource_Extension_Function, + class Dominance_Function, class Label_Allocator, class Visitor > +void 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, + // each inner vector corresponds to a pareto-optimal path + std::vector< + std::vector< typename graph_traits< Graph >::edge_descriptor > >& + pareto_optimal_solutions, + std::vector< Resource_Container >& pareto_optimal_resource_containers, + // to initialize the first label/resource container + // and to carry the type information + const Resource_Container& rc, const Resource_Extension_Function& ref, + const Dominance_Function& dominance, + // to specify the memory management strategy for the labels + Label_Allocator la, Visitor vis) +{ + r_c_shortest_paths(g, vertex_index_map, s, t, + pareto_optimal_solutions, pareto_optimal_resource_containers, rc, + ref, dominance, la, vis); +} + +// second overload: +// - return only one pareto-optimal solution +// - specify Label_Allocator and Visitor arguments +template < class Graph, class VertexIndexMap, class EdgeIndexMap, + class Resource_Container, class Resource_Extension_Function, + class Dominance_Function, class Label_Allocator, class Visitor > +void 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, + // to initialize the first label/resource container + // and to carry the type information + const Resource_Container& rc, const Resource_Extension_Function& ref, + const Dominance_Function& dominance, + // to specify the memory management strategy for the labels + Label_Allocator la, Visitor vis) +{ + r_c_shortest_paths(g, vertex_index_map, s, t, pareto_optimal_solution, pareto_optimal_resource_container, rc, ref, dominance, la, vis); +} + +// third overload: +// - return all pareto-optimal solutions +// - use default Label_Allocator and Visitor +template < class Graph, class VertexIndexMap, class EdgeIndexMap, + class Resource_Container, class Resource_Extension_Function, + class Dominance_Function > +void 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, + // each inner vector corresponds to a pareto-optimal path + std::vector< + std::vector< typename graph_traits< Graph >::edge_descriptor > >& + pareto_optimal_solutions, + std::vector< Resource_Container >& pareto_optimal_resource_containers, + // to initialize the first label/resource container + // and to carry the type information + const Resource_Container& rc, const Resource_Extension_Function& ref, + const Dominance_Function& dominance) +{ + r_c_shortest_paths(g, vertex_index_map, s, t, + pareto_optimal_solutions, pareto_optimal_resource_containers, rc, + ref, dominance, default_r_c_shortest_paths_allocator(), + default_r_c_shortest_paths_visitor()); +} + +// fourth overload: +// - return only one pareto-optimal solution +// - use default Label_Allocator and Visitor +template < class Graph, class VertexIndexMap, class EdgeIndexMap, + class Resource_Container, class Resource_Extension_Function, + class Dominance_Function > +void 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, + // to initialize the first label/resource container + // and to carry the type information + const Resource_Container& rc, const Resource_Extension_Function& ref, + const Dominance_Function& dominance) +{ + r_c_shortest_paths(g, vertex_index_map, s, t, pareto_optimal_solution, pareto_optimal_resource_container, rc, ref, dominance); +} // r_c_shortest_paths + + + // check_r_c_path function template < class Graph, class Resource_Container, class Resource_Extension_Function > From 0457790c985f58f6f2654b9bb2cef033482658db Mon Sep 17 00:00:00 2001 From: Andrea Cassioli Date: Thu, 23 Jul 2026 22:16:01 +0200 Subject: [PATCH 2/3] update tests and examples --- example/r_c_shortest_paths_example.cpp | 4 +- example/r_c_shortest_paths_example_old.cpp | 331 +++++++++ test/Jamfile.v2 | 3 + test/r_c_shortest_paths_test.cpp | 9 +- test/r_c_shortest_paths_test_old.cpp | 785 +++++++++++++++++++++ test/rcsp_custom_vertex_id.cpp | 3 +- test/rcsp_custom_vertex_id_old.cpp | 123 ++++ test/rcsp_single_solution.cpp | 3 +- test/rcsp_single_solution_old.cpp | 118 ++++ 9 files changed, 1368 insertions(+), 11 deletions(-) create mode 100644 example/r_c_shortest_paths_example_old.cpp create mode 100644 test/r_c_shortest_paths_test_old.cpp create mode 100644 test/rcsp_custom_vertex_id_old.cpp create mode 100644 test/rcsp_single_solution_old.cpp diff --git a/example/r_c_shortest_paths_example.cpp b/example/r_c_shortest_paths_example.cpp index 77326bb7c..edbed9cc9 100644 --- a/example/r_c_shortest_paths_example.cpp +++ b/example/r_c_shortest_paths_example.cpp @@ -249,7 +249,7 @@ int main() std::vector< spp_no_rc_res_cont > pareto_opt_rcs_no_rc; r_c_shortest_paths(g, get(&SPPRC_Example_Graph_Vert_Prop::num, g), - get(&SPPRC_Example_Graph_Arc_Prop::num, g), s, t, opt_solutions, + s, t, opt_solutions, pareto_opt_rcs_no_rc, spp_no_rc_res_cont(0), ref_no_res_cont(), dominance_no_res_cont(), std::allocator< r_c_shortest_paths_label< SPPRC_Example_Graph, @@ -278,7 +278,7 @@ int main() std::vector< spp_spptw_res_cont > pareto_opt_rcs_spptw; r_c_shortest_paths(g, get(&SPPRC_Example_Graph_Vert_Prop::num, g), - get(&SPPRC_Example_Graph_Arc_Prop::num, g), s, t, opt_solutions_spptw, + s, t, opt_solutions_spptw, pareto_opt_rcs_spptw, spp_spptw_res_cont(0, 0), ref_spptw(), dominance_spptw(), std::allocator< r_c_shortest_paths_label< SPPRC_Example_Graph, diff --git a/example/r_c_shortest_paths_example_old.cpp b/example/r_c_shortest_paths_example_old.cpp new file mode 100644 index 000000000..77326bb7c --- /dev/null +++ b/example/r_c_shortest_paths_example_old.cpp @@ -0,0 +1,331 @@ +// Copyright Michael Drexl 2005, 2006. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://boost.org/LICENSE_1_0.txt) + +// Example use of the resource-constrained shortest paths algorithm. +#include + +#ifdef BOOST_MSVC +#pragma warning(disable : 4267) +#endif + +#include + +#include +#include + +using namespace boost; + +struct SPPRC_Example_Graph_Vert_Prop +{ + SPPRC_Example_Graph_Vert_Prop(int n = 0, int e = 0, int l = 0) + : num(n), eat(e), lat(l) + { + } + int num; + // earliest arrival time + int eat; + // latest arrival time + int lat; +}; + +struct SPPRC_Example_Graph_Arc_Prop +{ + SPPRC_Example_Graph_Arc_Prop(int n = 0, int c = 0, int t = 0) + : num(n), cost(c), time(t) + { + } + int num; + // traversal cost + int cost; + // traversal time + int time; +}; + +using SPPRC_Example_Graph = adjacency_list< vecS, vecS, directedS, + SPPRC_Example_Graph_Vert_Prop, SPPRC_Example_Graph_Arc_Prop >; + +// data structures for spp without resource constraints: +// ResourceContainer model +struct spp_no_rc_res_cont +{ + spp_no_rc_res_cont(int c = 0) : cost(c) {}; + spp_no_rc_res_cont& operator=(const spp_no_rc_res_cont& other) + { + if (this == &other) + return *this; + this->~spp_no_rc_res_cont(); + new (this) spp_no_rc_res_cont(other); + return *this; + } + int cost; +}; + +bool operator==( + const spp_no_rc_res_cont& res_cont_1, const spp_no_rc_res_cont& res_cont_2) +{ + return (res_cont_1.cost == res_cont_2.cost); +} + +bool operator<( + const spp_no_rc_res_cont& res_cont_1, const spp_no_rc_res_cont& res_cont_2) +{ + return (res_cont_1.cost < res_cont_2.cost); +} + +// ResourceExtensionFunction model +class ref_no_res_cont +{ +public: + inline bool operator()(const SPPRC_Example_Graph& g, + spp_no_rc_res_cont& new_cont, const spp_no_rc_res_cont& old_cont, + graph_traits< SPPRC_Example_Graph >::edge_descriptor ed) const + { + new_cont.cost = old_cont.cost + g[ed].cost; + return true; + } +}; + +// DominanceFunction model +class dominance_no_res_cont +{ +public: + inline bool operator()(const spp_no_rc_res_cont& res_cont_1, + const spp_no_rc_res_cont& res_cont_2) const + { + // must be "<=" here!!! + // must NOT be "<"!!! + return res_cont_1.cost <= res_cont_2.cost; + // this is not a contradiction to the documentation + // the documentation says: + // "A label $l_1$ dominates a label $l_2$ if and only if both are + // resident at the same vertex, and if, for each resource, the resource + // consumption of $l_1$ is less than or equal to the resource + // consumption of $l_2$, and if there is at least one resource where + // $l_1$ has a lower resource consumption than $l_2$." one can think of + // a new label with a resource consumption equal to that of an old label + // as being dominated by that old label, because the new one will have a + // higher number and is created at a later point in time, so one can + // implicitly use the number or the creation time as a resource for + // tie-breaking + } +}; +// end data structures for spp without resource constraints: + +// data structures for shortest path problem with time windows (spptw) +// ResourceContainer model +struct spp_spptw_res_cont +{ + spp_spptw_res_cont(int c = 0, int t = 0) : cost(c), time(t) {} + spp_spptw_res_cont& operator=(const spp_spptw_res_cont& other) + { + if (this == &other) + return *this; + this->~spp_spptw_res_cont(); + new (this) spp_spptw_res_cont(other); + return *this; + } + int cost; + int time; +}; + +bool operator==( + const spp_spptw_res_cont& res_cont_1, const spp_spptw_res_cont& res_cont_2) +{ + return (res_cont_1.cost == res_cont_2.cost + && res_cont_1.time == res_cont_2.time); +} + +bool operator<( + const spp_spptw_res_cont& res_cont_1, const spp_spptw_res_cont& res_cont_2) +{ + if (res_cont_1.cost > res_cont_2.cost) + return false; + if (res_cont_1.cost == res_cont_2.cost) + return res_cont_1.time < res_cont_2.time; + return true; +} + +// ResourceExtensionFunction model +class ref_spptw +{ +public: + inline bool operator()(const SPPRC_Example_Graph& g, + spp_spptw_res_cont& new_cont, const spp_spptw_res_cont& old_cont, + graph_traits< SPPRC_Example_Graph >::edge_descriptor ed) const + { + const SPPRC_Example_Graph_Arc_Prop& arc_prop = get(edge_bundle, g)[ed]; + const SPPRC_Example_Graph_Vert_Prop& vert_prop + = get(vertex_bundle, g)[target(ed, g)]; + new_cont.cost = old_cont.cost + arc_prop.cost; + int& i_time = new_cont.time; + i_time = old_cont.time + arc_prop.time; + i_time < vert_prop.eat ? i_time = vert_prop.eat : 0; + return i_time <= vert_prop.lat ? true : false; + } +}; + +// DominanceFunction model +class dominance_spptw +{ +public: + inline bool operator()(const spp_spptw_res_cont& res_cont_1, + const spp_spptw_res_cont& res_cont_2) const + { + // must be "<=" here!!! + // must NOT be "<"!!! + return res_cont_1.cost <= res_cont_2.cost + && res_cont_1.time <= res_cont_2.time; + // this is not a contradiction to the documentation + // the documentation says: + // "A label $l_1$ dominates a label $l_2$ if and only if both are + // resident at the same vertex, and if, for each resource, the resource + // consumption of $l_1$ is less than or equal to the resource + // consumption of $l_2$, and if there is at least one resource where + // $l_1$ has a lower resource consumption than $l_2$." one can think of + // a new label with a resource consumption equal to that of an old label + // as being dominated by that old label, because the new one will have a + // higher number and is created at a later point in time, so one can + // implicitly use the number or the creation time as a resource for + // tie-breaking + } +}; +// end data structures for shortest path problem with time windows (spptw) + +// example graph structure and cost from +// http://www.boost.org/libs/graph/example/dijkstra-example.cpp +enum nodes +{ + A, + B, + C, + D, + E +}; +char name[] = "ABCDE"; + +int main() +{ + SPPRC_Example_Graph g; + + add_vertex(SPPRC_Example_Graph_Vert_Prop(A, 0, 0), g); + add_vertex(SPPRC_Example_Graph_Vert_Prop(B, 5, 20), g); + add_vertex(SPPRC_Example_Graph_Vert_Prop(C, 6, 10), g); + add_vertex(SPPRC_Example_Graph_Vert_Prop(D, 3, 12), g); + add_vertex(SPPRC_Example_Graph_Vert_Prop(E, 0, 100), g); + + add_edge(A, C, SPPRC_Example_Graph_Arc_Prop(0, 1, 5), g); + add_edge(B, B, SPPRC_Example_Graph_Arc_Prop(1, 2, 5), g); + add_edge(B, D, SPPRC_Example_Graph_Arc_Prop(2, 1, 2), g); + add_edge(B, E, SPPRC_Example_Graph_Arc_Prop(3, 2, 7), g); + add_edge(C, B, SPPRC_Example_Graph_Arc_Prop(4, 7, 3), g); + add_edge(C, D, SPPRC_Example_Graph_Arc_Prop(5, 3, 8), g); + add_edge(D, E, SPPRC_Example_Graph_Arc_Prop(6, 1, 3), g); + add_edge(E, A, SPPRC_Example_Graph_Arc_Prop(7, 1, 5), g); + add_edge(E, B, SPPRC_Example_Graph_Arc_Prop(8, 1, 4), g); + + // the unique shortest path from A to E in the dijkstra-example.cpp is + // A -> C -> D -> E + // its length is 5 + // the following code also yields this result + + // with the above time windows, this path is infeasible + // now, there are two shortest paths that are also feasible with respect to + // the vertex time windows: + // A -> C -> B -> D -> E and + // A -> C -> B -> E + // however, the latter has a longer total travel time and is therefore not + // pareto-optimal, i.e., it is dominated by the former path + // therefore, the code below returns only the former path + + // spp without resource constraints + graph_traits< SPPRC_Example_Graph >::vertex_descriptor s = A; + graph_traits< SPPRC_Example_Graph >::vertex_descriptor t = E; + + std::vector< + std::vector< graph_traits< SPPRC_Example_Graph >::edge_descriptor > > + opt_solutions; + std::vector< spp_no_rc_res_cont > pareto_opt_rcs_no_rc; + + r_c_shortest_paths(g, get(&SPPRC_Example_Graph_Vert_Prop::num, g), + get(&SPPRC_Example_Graph_Arc_Prop::num, g), s, t, opt_solutions, + pareto_opt_rcs_no_rc, spp_no_rc_res_cont(0), ref_no_res_cont(), + dominance_no_res_cont(), + std::allocator< r_c_shortest_paths_label< SPPRC_Example_Graph, + spp_no_rc_res_cont > >(), + default_r_c_shortest_paths_visitor()); + + std::cout << "SPP without resource constraints:" << std::endl; + std::cout << "Number of optimal solutions: "; + std::cout << static_cast< int >(opt_solutions.size()) << std::endl; + for (int i = 0; i < static_cast< int >(opt_solutions.size()); ++i) + { + std::cout << "The " << i << "th shortest path from A to E is: "; + std::cout << std::endl; + for (int j = static_cast< int >(opt_solutions[i].size()) - 1; j >= 0; + --j) + std::cout << name[source(opt_solutions[i][j], g)] << std::endl; + std::cout << "E" << std::endl; + std::cout << "Length: " << pareto_opt_rcs_no_rc[i].cost << std::endl; + } + std::cout << std::endl; + + // spptw + std::vector< + std::vector< graph_traits< SPPRC_Example_Graph >::edge_descriptor > > + opt_solutions_spptw; + std::vector< spp_spptw_res_cont > pareto_opt_rcs_spptw; + + r_c_shortest_paths(g, get(&SPPRC_Example_Graph_Vert_Prop::num, g), + get(&SPPRC_Example_Graph_Arc_Prop::num, g), s, t, opt_solutions_spptw, + pareto_opt_rcs_spptw, spp_spptw_res_cont(0, 0), ref_spptw(), + dominance_spptw(), + std::allocator< r_c_shortest_paths_label< SPPRC_Example_Graph, + spp_spptw_res_cont > >(), + default_r_c_shortest_paths_visitor()); + + std::cout << "SPP with time windows:" << std::endl; + std::cout << "Number of optimal solutions: "; + std::cout << static_cast< int >(opt_solutions_spptw.size()) << std::endl; + for (int i = 0; i < static_cast< int >(opt_solutions_spptw.size()); ++i) + { + std::cout << "The " << i << "th shortest path from A to E is: "; + std::cout << std::endl; + for (int j = static_cast< int >(opt_solutions_spptw[i].size()) - 1; + j >= 0; --j) + std::cout << name[source(opt_solutions_spptw[i][j], g)] + << std::endl; + std::cout << "E" << std::endl; + std::cout << "Length: " << pareto_opt_rcs_spptw[i].cost << std::endl; + std::cout << "Time: " << pareto_opt_rcs_spptw[i].time << std::endl; + } + + // utility function check_r_c_path example + std::cout << std::endl; + bool b_is_a_path_at_all = false; + bool b_feasible = false; + bool b_correctly_extended = false; + spp_spptw_res_cont actual_final_resource_levels(0, 0); + graph_traits< SPPRC_Example_Graph >::edge_descriptor ed_last_extended_arc; + check_r_c_path(g, opt_solutions_spptw[0], spp_spptw_res_cont(0, 0), true, + pareto_opt_rcs_spptw[0], actual_final_resource_levels, ref_spptw(), + b_is_a_path_at_all, b_feasible, b_correctly_extended, + ed_last_extended_arc); + if (!b_is_a_path_at_all) + std::cout << "Not a path." << std::endl; + if (!b_feasible) + std::cout << "Not a feasible path." << std::endl; + if (!b_correctly_extended) + std::cout << "Not correctly extended." << std::endl; + if (b_is_a_path_at_all && b_feasible && b_correctly_extended) + { + std::cout << "Actual final resource levels:" << std::endl; + std::cout << "Length: " << actual_final_resource_levels.cost + << std::endl; + std::cout << "Time: " << actual_final_resource_levels.time << std::endl; + std::cout << "OK." << std::endl; + } + + return 0; +} diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index d05a0a7ef..5b5cd38e0 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -131,8 +131,11 @@ alias graph_test_regular : [ run make_maximal_planar_test.cpp ] [ run named_vertices_test.cpp ] [ run r_c_shortest_paths_test.cpp ] + [ run r_c_shortest_paths_test_old.cpp ] + [ run rcsp_custom_vertex_id_old.cpp ] [ run rcsp_custom_vertex_id.cpp ] [ run rcsp_single_solution.cpp ] + [ run rcsp_single_solution_old.cpp ] [ run is_straight_line_draw_test.cpp ] [ run metric_tsp_approx.cpp /boost/timer//boost_timer : metric_tsp_approx.graph : : ] [ compile dimacs.cpp ] diff --git a/test/r_c_shortest_paths_test.cpp b/test/r_c_shortest_paths_test.cpp index 7a80d7c1c..211eea0c4 100644 --- a/test/r_c_shortest_paths_test.cpp +++ b/test/r_c_shortest_paths_test.cpp @@ -363,8 +363,7 @@ int main(int, char*[]) { for (int t = 0; t < 10; ++t) { - r_c_shortest_paths(g, get(&SPPRC_Example_Graph_Vert_Prop::num, g), - get(&SPPRC_Example_Graph_Arc_Prop::num, g), s, t, opt_solutions, + r_c_shortest_paths(g, get(&SPPRC_Example_Graph_Vert_Prop::num, g), s, t, opt_solutions, pareto_opt_rcs_no_rc, spp_no_rc_res_cont(0), ref_no_res_cont(), dominance_no_res_cont(), std::allocator< r_c_shortest_paths_label< SPPRC_Example_Graph, @@ -523,7 +522,7 @@ int main(int, char*[]) for (int t = 0; t < 10; ++t) { r_c_shortest_paths(g, get(&SPPRC_Example_Graph_Vert_Prop::num, g), - get(&SPPRC_Example_Graph_Arc_Prop::num, g), s, t, + s, t, opt_solutions_spptw, pareto_opt_rcs_spptw, // be careful, do not simply take 0 as initial value for time spp_spptw_res_cont(0, g[s].eat), ref_spptw(), dominance_spptw(), @@ -685,7 +684,7 @@ int main(int, char*[]) opt_solution; spp_spptw_res_cont pareto_opt_rc; r_c_shortest_paths(g2, get(&SPPRC_Example_Graph_Vert_Prop::num, g2), - get(&SPPRC_Example_Graph_Arc_Prop::num, g2), 0, 3, opt_solution, + 0, 3, opt_solution, pareto_opt_rc, spp_spptw_res_cont(0, 0), ref_spptw(), dominance_spptw(), std::allocator< r_c_shortest_paths_label< SPPRC_Example_Graph, spp_spptw_res_cont > >(), @@ -730,7 +729,7 @@ int main(int, char*[]) graph_traits< SPPRC_Example_Graph >::vertex_descriptor g3_source = 0, g3_target = 1; r_c_shortest_paths(g3, get(&SPPRC_Example_Graph_Vert_Prop::num, g3), - get(&SPPRC_Example_Graph_Arc_Prop::num, g3), g3_source, g3_target, + g3_source, g3_target, pareto_opt_marked_solutions, pareto_opt_marked_resource_containers, spp_spptw_marked_res_cont(0, 0, 0), ref_spptw_marked(), dominance_spptw_marked(), diff --git a/test/r_c_shortest_paths_test_old.cpp b/test/r_c_shortest_paths_test_old.cpp new file mode 100644 index 000000000..7a80d7c1c --- /dev/null +++ b/test/r_c_shortest_paths_test_old.cpp @@ -0,0 +1,785 @@ +// Copyright Michael Drexl 2005, 2006. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://boost.org/LICENSE_1_0.txt) + +#include + +#ifdef BOOST_MSVC +#pragma warning(disable : 4267) +#endif + +#include +//#include + +#include +#include +#include + +using namespace boost; + +struct SPPRC_Example_Graph_Vert_Prop +{ + SPPRC_Example_Graph_Vert_Prop(int n = 0, int e = 0, int l = 0) + : num(n), eat(e), lat(l) + { + } + int num; + // earliest arrival time + int eat; + // latest arrival time + int lat; +}; + +struct SPPRC_Example_Graph_Arc_Prop +{ + SPPRC_Example_Graph_Arc_Prop(int n = 0, int c = 0, int t = 0) + : num(n), cost(c), time(t) + { + } + int num; + // traversal cost + int cost; + // traversal time + int time; +}; + +typedef adjacency_list< vecS, vecS, directedS, SPPRC_Example_Graph_Vert_Prop, + SPPRC_Example_Graph_Arc_Prop > + SPPRC_Example_Graph; + +// data structures for spp without resource constraints: +// ResourceContainer model +struct spp_no_rc_res_cont +{ + spp_no_rc_res_cont(int c = 0) : cost(c) {}; + spp_no_rc_res_cont& operator=(const spp_no_rc_res_cont& other) + { + if (this == &other) + return *this; + this->~spp_no_rc_res_cont(); + new (this) spp_no_rc_res_cont(other); + return *this; + } + int cost; +}; + +bool operator==( + const spp_no_rc_res_cont& res_cont_1, const spp_no_rc_res_cont& res_cont_2) +{ + return (res_cont_1.cost == res_cont_2.cost); +} + +bool operator<( + const spp_no_rc_res_cont& res_cont_1, const spp_no_rc_res_cont& res_cont_2) +{ + return (res_cont_1.cost < res_cont_2.cost); +} + +// ResourceExtensionFunction model +class ref_no_res_cont +{ +public: + inline bool operator()(const SPPRC_Example_Graph& g, + spp_no_rc_res_cont& new_cont, const spp_no_rc_res_cont& old_cont, + graph_traits< SPPRC_Example_Graph >::edge_descriptor ed) const + { + new_cont.cost = old_cont.cost + g[ed].cost; + return true; + } +}; + +// DominanceFunction model +class dominance_no_res_cont +{ +public: + inline bool operator()(const spp_no_rc_res_cont& res_cont_1, + const spp_no_rc_res_cont& res_cont_2) const + { + // must be "<=" here!!! + // must NOT be "<"!!! + return res_cont_1.cost <= res_cont_2.cost; + // this is not a contradiction to the documentation + // the documentation says: + // "A label $l_1$ dominates a label $l_2$ if and only if both are + // resident at the same vertex, and if, for each resource, the resource + // consumption of $l_1$ is less than or equal to the resource + // consumption of $l_2$, and if there is at least one resource where + // $l_1$ has a lower resource consumption than $l_2$." one can think of + // a new label with a resource consumption equal to that of an old label + // as being dominated by that old label, because the new one will have a + // higher number and is created at a later point in time, so one can + // implicitly use the number or the creation time as a resource for + // tie-breaking + } +}; +// end data structures for spp without resource constraints: + +// data structures for shortest path problem with time windows (spptw) +// ResourceContainer model +struct spp_spptw_res_cont +{ + spp_spptw_res_cont(int c = 0, int t = 0) : cost(c), time(t) {} + spp_spptw_res_cont& operator=(const spp_spptw_res_cont& other) + { + if (this == &other) + return *this; + this->~spp_spptw_res_cont(); + new (this) spp_spptw_res_cont(other); + return *this; + } + int cost; + int time; +}; + +bool operator==( + const spp_spptw_res_cont& res_cont_1, const spp_spptw_res_cont& res_cont_2) +{ + return (res_cont_1.cost == res_cont_2.cost + && res_cont_1.time == res_cont_2.time); +} + +bool operator<( + const spp_spptw_res_cont& res_cont_1, const spp_spptw_res_cont& res_cont_2) +{ + if (res_cont_1.cost > res_cont_2.cost) + return false; + if (res_cont_1.cost == res_cont_2.cost) + return res_cont_1.time < res_cont_2.time; + return true; +} + +// ResourceExtensionFunction model +class ref_spptw +{ +public: + inline bool operator()(const SPPRC_Example_Graph& g, + spp_spptw_res_cont& new_cont, const spp_spptw_res_cont& old_cont, + graph_traits< SPPRC_Example_Graph >::edge_descriptor ed) const + { + const SPPRC_Example_Graph_Arc_Prop& arc_prop = get(edge_bundle, g)[ed]; + const SPPRC_Example_Graph_Vert_Prop& vert_prop + = get(vertex_bundle, g)[target(ed, g)]; + new_cont.cost = old_cont.cost + arc_prop.cost; + int& i_time = new_cont.time; + i_time = old_cont.time + arc_prop.time; + i_time < vert_prop.eat ? i_time = vert_prop.eat : 0; + return i_time <= vert_prop.lat ? true : false; + } +}; + +// DominanceFunction model +class dominance_spptw +{ +public: + inline bool operator()(const spp_spptw_res_cont& res_cont_1, + const spp_spptw_res_cont& res_cont_2) const + { + // must be "<=" here!!! + // must NOT be "<"!!! + return res_cont_1.cost <= res_cont_2.cost + && res_cont_1.time <= res_cont_2.time; + // this is not a contradiction to the documentation + // the documentation says: + // "A label $l_1$ dominates a label $l_2$ if and only if both are + // resident at the same vertex, and if, for each resource, the resource + // consumption of $l_1$ is less than or equal to the resource + // consumption of $l_2$, and if there is at least one resource where + // $l_1$ has a lower resource consumption than $l_2$." one can think of + // a new label with a resource consumption equal to that of an old label + // as being dominated by that old label, because the new one will have a + // higher number and is created at a later point in time, so one can + // implicitly use the number or the creation time as a resource for + // tie-breaking + } +}; +// end data structures for shortest path problem with time windows (spptw) + +struct spp_spptw_marked_res_cont +{ + spp_spptw_marked_res_cont( + SPPRC_Example_Graph::vertex_descriptor v, int c = 0, int t = 0) + : cost(c), time(t), marked() + { + marked.insert(v); + } + spp_spptw_marked_res_cont& operator=(const spp_spptw_marked_res_cont& other) + { + if (this == &other) + return *this; + this->~spp_spptw_marked_res_cont(); + new (this) spp_spptw_marked_res_cont(other); + return *this; + } + int cost; + int time; + std::set< SPPRC_Example_Graph::vertex_descriptor > marked; +}; + +bool operator==(const spp_spptw_marked_res_cont& res_cont_1, + const spp_spptw_marked_res_cont& res_cont_2) +{ + return res_cont_1.cost == res_cont_2.cost + && res_cont_1.time == res_cont_2.time + && res_cont_1.marked == res_cont_2.marked; +} + +bool operator<(const spp_spptw_marked_res_cont& res_cont_1, + const spp_spptw_marked_res_cont& res_cont_2) +{ + if (res_cont_1.cost > res_cont_2.cost || res_cont_1.time > res_cont_2.time) + { + return false; + } + + if (!std::includes(res_cont_2.marked.begin(), res_cont_2.marked.end(), + res_cont_1.marked.begin(), res_cont_1.marked.end())) + { + return false; + } + + if (res_cont_1.cost == res_cont_2.cost) + { + return res_cont_1.time < res_cont_2.time; + } + return true; +} + +class ref_spptw_marked +{ +public: + inline bool operator()(const SPPRC_Example_Graph& g, + spp_spptw_marked_res_cont& new_cont, + const spp_spptw_marked_res_cont& old_cont, + graph_traits< SPPRC_Example_Graph >::edge_descriptor ed) const + { + const graph_traits< SPPRC_Example_Graph >::vertex_descriptor dest + = target(ed, g); + + if (old_cont.marked.find(dest) != old_cont.marked.end()) + { + return false; + } + + const SPPRC_Example_Graph_Arc_Prop& arc_prop = get(edge_bundle, g)[ed]; + const SPPRC_Example_Graph_Vert_Prop& vert_prop + = get(vertex_bundle, g)[dest]; + new_cont.cost = old_cont.cost + arc_prop.cost; + new_cont.marked = old_cont.marked; + new_cont.marked.insert(dest); + int& i_time = new_cont.time; + i_time = old_cont.time + arc_prop.time; + i_time < vert_prop.eat ? i_time = vert_prop.eat : 0; + return i_time <= vert_prop.lat; + } +}; + +class dominance_spptw_marked +{ +public: + inline bool operator()(const spp_spptw_marked_res_cont& res_cont_1, + const spp_spptw_marked_res_cont& res_cont_2) const + { + return res_cont_1.time <= res_cont_2.time + && res_cont_1.cost <= res_cont_2.cost + && std::includes(res_cont_1.marked.begin(), res_cont_1.marked.end(), + res_cont_2.marked.begin(), res_cont_2.marked.end()); + } +}; + +int main(int, char*[]) +{ + SPPRC_Example_Graph g; + add_vertex(SPPRC_Example_Graph_Vert_Prop(0, 0, 1000000000), g); + add_vertex(SPPRC_Example_Graph_Vert_Prop(1, 56, 142), g); + add_vertex(SPPRC_Example_Graph_Vert_Prop(2, 0, 1000000000), g); + add_vertex(SPPRC_Example_Graph_Vert_Prop(3, 89, 178), g); + add_vertex(SPPRC_Example_Graph_Vert_Prop(4, 0, 1000000000), g); + add_vertex(SPPRC_Example_Graph_Vert_Prop(5, 49, 76), g); + add_vertex(SPPRC_Example_Graph_Vert_Prop(6, 0, 1000000000), g); + add_vertex(SPPRC_Example_Graph_Vert_Prop(7, 98, 160), g); + add_vertex(SPPRC_Example_Graph_Vert_Prop(8, 0, 1000000000), g); + add_vertex(SPPRC_Example_Graph_Vert_Prop(9, 90, 158), g); + add_edge(0, 7, SPPRC_Example_Graph_Arc_Prop(6, 33, 2), g); + add_edge(0, 6, SPPRC_Example_Graph_Arc_Prop(5, 31, 6), g); + add_edge(0, 4, SPPRC_Example_Graph_Arc_Prop(3, 14, 4), g); + add_edge(0, 1, SPPRC_Example_Graph_Arc_Prop(0, 43, 8), g); + add_edge(0, 4, SPPRC_Example_Graph_Arc_Prop(4, 28, 10), g); + add_edge(0, 3, SPPRC_Example_Graph_Arc_Prop(1, 31, 10), g); + add_edge(0, 3, SPPRC_Example_Graph_Arc_Prop(2, 1, 7), g); + add_edge(0, 9, SPPRC_Example_Graph_Arc_Prop(7, 25, 9), g); + add_edge(1, 0, SPPRC_Example_Graph_Arc_Prop(8, 37, 4), g); + add_edge(1, 6, SPPRC_Example_Graph_Arc_Prop(9, 7, 3), g); + add_edge(2, 6, SPPRC_Example_Graph_Arc_Prop(12, 6, 7), g); + add_edge(2, 3, SPPRC_Example_Graph_Arc_Prop(10, 13, 7), g); + add_edge(2, 3, SPPRC_Example_Graph_Arc_Prop(11, 49, 9), g); + add_edge(2, 8, SPPRC_Example_Graph_Arc_Prop(13, 47, 5), g); + add_edge(3, 4, SPPRC_Example_Graph_Arc_Prop(17, 5, 10), g); + add_edge(3, 1, SPPRC_Example_Graph_Arc_Prop(15, 47, 1), g); + add_edge(3, 2, SPPRC_Example_Graph_Arc_Prop(16, 26, 9), g); + add_edge(3, 9, SPPRC_Example_Graph_Arc_Prop(21, 24, 10), g); + add_edge(3, 7, SPPRC_Example_Graph_Arc_Prop(20, 50, 10), g); + add_edge(3, 0, SPPRC_Example_Graph_Arc_Prop(14, 41, 4), g); + add_edge(3, 6, SPPRC_Example_Graph_Arc_Prop(19, 6, 1), g); + add_edge(3, 4, SPPRC_Example_Graph_Arc_Prop(18, 8, 1), g); + add_edge(4, 5, SPPRC_Example_Graph_Arc_Prop(26, 38, 4), g); + add_edge(4, 9, SPPRC_Example_Graph_Arc_Prop(27, 32, 10), g); + add_edge(4, 3, SPPRC_Example_Graph_Arc_Prop(24, 40, 3), g); + add_edge(4, 0, SPPRC_Example_Graph_Arc_Prop(22, 7, 3), g); + add_edge(4, 3, SPPRC_Example_Graph_Arc_Prop(25, 28, 9), g); + add_edge(4, 2, SPPRC_Example_Graph_Arc_Prop(23, 39, 6), g); + add_edge(5, 8, SPPRC_Example_Graph_Arc_Prop(32, 6, 2), g); + add_edge(5, 2, SPPRC_Example_Graph_Arc_Prop(30, 26, 10), g); + add_edge(5, 0, SPPRC_Example_Graph_Arc_Prop(28, 38, 9), g); + add_edge(5, 2, SPPRC_Example_Graph_Arc_Prop(31, 48, 10), g); + add_edge(5, 9, SPPRC_Example_Graph_Arc_Prop(33, 49, 2), g); + add_edge(5, 1, SPPRC_Example_Graph_Arc_Prop(29, 22, 7), g); + add_edge(6, 1, SPPRC_Example_Graph_Arc_Prop(34, 15, 7), g); + add_edge(6, 7, SPPRC_Example_Graph_Arc_Prop(35, 20, 3), g); + add_edge(7, 9, SPPRC_Example_Graph_Arc_Prop(40, 1, 3), g); + add_edge(7, 0, SPPRC_Example_Graph_Arc_Prop(36, 23, 5), g); + add_edge(7, 6, SPPRC_Example_Graph_Arc_Prop(38, 36, 2), g); + add_edge(7, 6, SPPRC_Example_Graph_Arc_Prop(39, 18, 10), g); + add_edge(7, 2, SPPRC_Example_Graph_Arc_Prop(37, 2, 1), g); + add_edge(8, 5, SPPRC_Example_Graph_Arc_Prop(46, 36, 5), g); + add_edge(8, 1, SPPRC_Example_Graph_Arc_Prop(42, 13, 10), g); + add_edge(8, 0, SPPRC_Example_Graph_Arc_Prop(41, 40, 5), g); + add_edge(8, 1, SPPRC_Example_Graph_Arc_Prop(43, 32, 8), g); + add_edge(8, 6, SPPRC_Example_Graph_Arc_Prop(47, 25, 1), g); + add_edge(8, 2, SPPRC_Example_Graph_Arc_Prop(44, 44, 3), g); + add_edge(8, 3, SPPRC_Example_Graph_Arc_Prop(45, 11, 9), g); + add_edge(9, 0, SPPRC_Example_Graph_Arc_Prop(48, 41, 5), g); + add_edge(9, 1, SPPRC_Example_Graph_Arc_Prop(49, 44, 7), g); + + // spp without resource constraints + + std::vector< + std::vector< graph_traits< SPPRC_Example_Graph >::edge_descriptor > > + opt_solutions; + std::vector< spp_no_rc_res_cont > pareto_opt_rcs_no_rc; + std::vector< int > i_vec_opt_solutions_spp_no_rc; + // std::cout << "r_c_shortest_paths:" << std::endl; + for (int s = 0; s < 10; ++s) + { + for (int t = 0; t < 10; ++t) + { + r_c_shortest_paths(g, get(&SPPRC_Example_Graph_Vert_Prop::num, g), + get(&SPPRC_Example_Graph_Arc_Prop::num, g), s, t, opt_solutions, + pareto_opt_rcs_no_rc, spp_no_rc_res_cont(0), ref_no_res_cont(), + dominance_no_res_cont(), + std::allocator< r_c_shortest_paths_label< SPPRC_Example_Graph, + spp_no_rc_res_cont > >(), + default_r_c_shortest_paths_visitor()); + i_vec_opt_solutions_spp_no_rc.push_back( + pareto_opt_rcs_no_rc[0].cost); + // std::cout << "From " << s << " to " << t << ": "; + // std::cout << pareto_opt_rcs_no_rc[0].cost << std::endl; + } + } + + // std::vector::vertex_descriptor> + // p( num_vertices( g ) ); + // std::vector d( num_vertices( g ) ); + // std::vector i_vec_dijkstra_distances; + // std::cout << "Dijkstra:" << std::endl; + // for( int s = 0; s < 10; ++s ) + //{ + // dijkstra_shortest_paths( g, + // s, + // &p[0], + // &d[0], + // get( &SPPRC_Example_Graph_Arc_Prop::cost, g ), + // get( &SPPRC_Example_Graph_Vert_Prop::num, g ), + // std::less(), + // closed_plus(), + // (std::numeric_limits::max)(), + // 0, + // default_dijkstra_visitor() ); + // for( int t = 0; t < 10; ++t ) + // { + // i_vec_dijkstra_distances.push_back( d[t] ); + // std::cout << "From " << s << " to " << t << ": " << d[t] << std::endl; + // } + //} + + std::vector< int > i_vec_correct_solutions; + i_vec_correct_solutions.push_back(0); + i_vec_correct_solutions.push_back(22); + i_vec_correct_solutions.push_back(27); + i_vec_correct_solutions.push_back(1); + i_vec_correct_solutions.push_back(6); + i_vec_correct_solutions.push_back(44); + i_vec_correct_solutions.push_back(7); + i_vec_correct_solutions.push_back(27); + i_vec_correct_solutions.push_back(50); + i_vec_correct_solutions.push_back(25); + i_vec_correct_solutions.push_back(37); + i_vec_correct_solutions.push_back(0); + i_vec_correct_solutions.push_back(29); + i_vec_correct_solutions.push_back(38); + i_vec_correct_solutions.push_back(43); + i_vec_correct_solutions.push_back(81); + i_vec_correct_solutions.push_back(7); + i_vec_correct_solutions.push_back(27); + i_vec_correct_solutions.push_back(76); + i_vec_correct_solutions.push_back(28); + i_vec_correct_solutions.push_back(25); + i_vec_correct_solutions.push_back(21); + i_vec_correct_solutions.push_back(0); + i_vec_correct_solutions.push_back(13); + i_vec_correct_solutions.push_back(18); + i_vec_correct_solutions.push_back(56); + i_vec_correct_solutions.push_back(6); + i_vec_correct_solutions.push_back(26); + i_vec_correct_solutions.push_back(47); + i_vec_correct_solutions.push_back(27); + i_vec_correct_solutions.push_back(12); + i_vec_correct_solutions.push_back(21); + i_vec_correct_solutions.push_back(26); + i_vec_correct_solutions.push_back(0); + i_vec_correct_solutions.push_back(5); + i_vec_correct_solutions.push_back(43); + i_vec_correct_solutions.push_back(6); + i_vec_correct_solutions.push_back(26); + i_vec_correct_solutions.push_back(49); + i_vec_correct_solutions.push_back(24); + i_vec_correct_solutions.push_back(7); + i_vec_correct_solutions.push_back(29); + i_vec_correct_solutions.push_back(34); + i_vec_correct_solutions.push_back(8); + i_vec_correct_solutions.push_back(0); + i_vec_correct_solutions.push_back(38); + i_vec_correct_solutions.push_back(14); + i_vec_correct_solutions.push_back(34); + i_vec_correct_solutions.push_back(44); + i_vec_correct_solutions.push_back(32); + i_vec_correct_solutions.push_back(29); + i_vec_correct_solutions.push_back(19); + i_vec_correct_solutions.push_back(26); + i_vec_correct_solutions.push_back(17); + i_vec_correct_solutions.push_back(22); + i_vec_correct_solutions.push_back(0); + i_vec_correct_solutions.push_back(23); + i_vec_correct_solutions.push_back(43); + i_vec_correct_solutions.push_back(6); + i_vec_correct_solutions.push_back(41); + i_vec_correct_solutions.push_back(43); + i_vec_correct_solutions.push_back(15); + i_vec_correct_solutions.push_back(22); + i_vec_correct_solutions.push_back(35); + i_vec_correct_solutions.push_back(40); + i_vec_correct_solutions.push_back(78); + i_vec_correct_solutions.push_back(0); + i_vec_correct_solutions.push_back(20); + i_vec_correct_solutions.push_back(69); + i_vec_correct_solutions.push_back(21); + i_vec_correct_solutions.push_back(23); + i_vec_correct_solutions.push_back(23); + i_vec_correct_solutions.push_back(2); + i_vec_correct_solutions.push_back(15); + i_vec_correct_solutions.push_back(20); + i_vec_correct_solutions.push_back(58); + i_vec_correct_solutions.push_back(8); + i_vec_correct_solutions.push_back(0); + i_vec_correct_solutions.push_back(49); + i_vec_correct_solutions.push_back(1); + i_vec_correct_solutions.push_back(23); + i_vec_correct_solutions.push_back(13); + i_vec_correct_solutions.push_back(37); + i_vec_correct_solutions.push_back(11); + i_vec_correct_solutions.push_back(16); + i_vec_correct_solutions.push_back(36); + i_vec_correct_solutions.push_back(17); + i_vec_correct_solutions.push_back(37); + i_vec_correct_solutions.push_back(0); + i_vec_correct_solutions.push_back(35); + i_vec_correct_solutions.push_back(41); + i_vec_correct_solutions.push_back(44); + i_vec_correct_solutions.push_back(68); + i_vec_correct_solutions.push_back(42); + i_vec_correct_solutions.push_back(47); + i_vec_correct_solutions.push_back(85); + i_vec_correct_solutions.push_back(48); + i_vec_correct_solutions.push_back(68); + i_vec_correct_solutions.push_back(91); + i_vec_correct_solutions.push_back(0); + BOOST_TEST( + i_vec_opt_solutions_spp_no_rc.size() == i_vec_correct_solutions.size()); + for (int i = 0; i < static_cast< int >(i_vec_correct_solutions.size()); ++i) + BOOST_TEST( + i_vec_opt_solutions_spp_no_rc[i] == i_vec_correct_solutions[i]); + + // spptw + std::vector< + std::vector< graph_traits< SPPRC_Example_Graph >::edge_descriptor > > + opt_solutions_spptw; + std::vector< spp_spptw_res_cont > pareto_opt_rcs_spptw; + std::vector< std::vector< std::vector< std::vector< + graph_traits< SPPRC_Example_Graph >::edge_descriptor > > > > + vec_vec_vec_vec_opt_solutions_spptw(10); + + for (int s = 0; s < 10; ++s) + { + for (int t = 0; t < 10; ++t) + { + r_c_shortest_paths(g, get(&SPPRC_Example_Graph_Vert_Prop::num, g), + get(&SPPRC_Example_Graph_Arc_Prop::num, g), s, t, + opt_solutions_spptw, pareto_opt_rcs_spptw, + // be careful, do not simply take 0 as initial value for time + spp_spptw_res_cont(0, g[s].eat), ref_spptw(), dominance_spptw(), + std::allocator< r_c_shortest_paths_label< SPPRC_Example_Graph, + spp_spptw_res_cont > >(), + default_r_c_shortest_paths_visitor()); + vec_vec_vec_vec_opt_solutions_spptw[s].push_back( + opt_solutions_spptw); + if (opt_solutions_spptw.size()) + { + bool b_is_a_path_at_all = false; + bool b_feasible = false; + bool b_correctly_extended = false; + spp_spptw_res_cont actual_final_resource_levels(0, 0); + graph_traits< SPPRC_Example_Graph >::edge_descriptor + ed_last_extended_arc; + check_r_c_path(g, opt_solutions_spptw[0], + spp_spptw_res_cont(0, g[s].eat), true, + pareto_opt_rcs_spptw[0], actual_final_resource_levels, + ref_spptw(), b_is_a_path_at_all, b_feasible, + b_correctly_extended, ed_last_extended_arc); + BOOST_TEST( + b_is_a_path_at_all && b_feasible && b_correctly_extended); + b_is_a_path_at_all = false; + b_feasible = false; + b_correctly_extended = false; + spp_spptw_res_cont actual_final_resource_levels2(0, 0); + graph_traits< SPPRC_Example_Graph >::edge_descriptor + ed_last_extended_arc2; + check_r_c_path(g, opt_solutions_spptw[0], + spp_spptw_res_cont(0, g[s].eat), false, + pareto_opt_rcs_spptw[0], actual_final_resource_levels2, + ref_spptw(), b_is_a_path_at_all, b_feasible, + b_correctly_extended, ed_last_extended_arc2); + BOOST_TEST( + b_is_a_path_at_all && b_feasible && b_correctly_extended); + } + } + } + + std::vector< int > i_vec_correct_num_solutions_spptw; + i_vec_correct_num_solutions_spptw.push_back(1); + i_vec_correct_num_solutions_spptw.push_back(2); + i_vec_correct_num_solutions_spptw.push_back(3); + i_vec_correct_num_solutions_spptw.push_back(1); + i_vec_correct_num_solutions_spptw.push_back(3); + i_vec_correct_num_solutions_spptw.push_back(1); + i_vec_correct_num_solutions_spptw.push_back(2); + i_vec_correct_num_solutions_spptw.push_back(1); + i_vec_correct_num_solutions_spptw.push_back(2); + i_vec_correct_num_solutions_spptw.push_back(1); + i_vec_correct_num_solutions_spptw.push_back(1); + i_vec_correct_num_solutions_spptw.push_back(1); + i_vec_correct_num_solutions_spptw.push_back(4); + i_vec_correct_num_solutions_spptw.push_back(1); + i_vec_correct_num_solutions_spptw.push_back(3); + i_vec_correct_num_solutions_spptw.push_back(1); + i_vec_correct_num_solutions_spptw.push_back(1); + i_vec_correct_num_solutions_spptw.push_back(1); + i_vec_correct_num_solutions_spptw.push_back(2); + i_vec_correct_num_solutions_spptw.push_back(2); + i_vec_correct_num_solutions_spptw.push_back(4); + i_vec_correct_num_solutions_spptw.push_back(1); + i_vec_correct_num_solutions_spptw.push_back(1); + i_vec_correct_num_solutions_spptw.push_back(1); + i_vec_correct_num_solutions_spptw.push_back(4); + i_vec_correct_num_solutions_spptw.push_back(1); + i_vec_correct_num_solutions_spptw.push_back(2); + i_vec_correct_num_solutions_spptw.push_back(1); + i_vec_correct_num_solutions_spptw.push_back(1); + i_vec_correct_num_solutions_spptw.push_back(3); + i_vec_correct_num_solutions_spptw.push_back(2); + i_vec_correct_num_solutions_spptw.push_back(2); + i_vec_correct_num_solutions_spptw.push_back(2); + i_vec_correct_num_solutions_spptw.push_back(1); + i_vec_correct_num_solutions_spptw.push_back(2); + i_vec_correct_num_solutions_spptw.push_back(0); + i_vec_correct_num_solutions_spptw.push_back(1); + i_vec_correct_num_solutions_spptw.push_back(1); + i_vec_correct_num_solutions_spptw.push_back(2); + i_vec_correct_num_solutions_spptw.push_back(1); + i_vec_correct_num_solutions_spptw.push_back(1); + i_vec_correct_num_solutions_spptw.push_back(2); + i_vec_correct_num_solutions_spptw.push_back(2); + i_vec_correct_num_solutions_spptw.push_back(1); + i_vec_correct_num_solutions_spptw.push_back(1); + i_vec_correct_num_solutions_spptw.push_back(1); + i_vec_correct_num_solutions_spptw.push_back(2); + i_vec_correct_num_solutions_spptw.push_back(1); + i_vec_correct_num_solutions_spptw.push_back(2); + i_vec_correct_num_solutions_spptw.push_back(1); + i_vec_correct_num_solutions_spptw.push_back(4); + i_vec_correct_num_solutions_spptw.push_back(2); + i_vec_correct_num_solutions_spptw.push_back(2); + i_vec_correct_num_solutions_spptw.push_back(1); + i_vec_correct_num_solutions_spptw.push_back(4); + i_vec_correct_num_solutions_spptw.push_back(1); + i_vec_correct_num_solutions_spptw.push_back(4); + i_vec_correct_num_solutions_spptw.push_back(1); + i_vec_correct_num_solutions_spptw.push_back(1); + i_vec_correct_num_solutions_spptw.push_back(2); + i_vec_correct_num_solutions_spptw.push_back(2); + i_vec_correct_num_solutions_spptw.push_back(1); + i_vec_correct_num_solutions_spptw.push_back(4); + i_vec_correct_num_solutions_spptw.push_back(2); + i_vec_correct_num_solutions_spptw.push_back(5); + i_vec_correct_num_solutions_spptw.push_back(1); + i_vec_correct_num_solutions_spptw.push_back(1); + i_vec_correct_num_solutions_spptw.push_back(1); + i_vec_correct_num_solutions_spptw.push_back(2); + i_vec_correct_num_solutions_spptw.push_back(2); + i_vec_correct_num_solutions_spptw.push_back(1); + i_vec_correct_num_solutions_spptw.push_back(3); + i_vec_correct_num_solutions_spptw.push_back(1); + i_vec_correct_num_solutions_spptw.push_back(1); + i_vec_correct_num_solutions_spptw.push_back(2); + i_vec_correct_num_solutions_spptw.push_back(0); + i_vec_correct_num_solutions_spptw.push_back(2); + i_vec_correct_num_solutions_spptw.push_back(1); + i_vec_correct_num_solutions_spptw.push_back(1); + i_vec_correct_num_solutions_spptw.push_back(1); + i_vec_correct_num_solutions_spptw.push_back(3); + i_vec_correct_num_solutions_spptw.push_back(1); + i_vec_correct_num_solutions_spptw.push_back(2); + i_vec_correct_num_solutions_spptw.push_back(1); + i_vec_correct_num_solutions_spptw.push_back(3); + i_vec_correct_num_solutions_spptw.push_back(1); + i_vec_correct_num_solutions_spptw.push_back(3); + i_vec_correct_num_solutions_spptw.push_back(1); + i_vec_correct_num_solutions_spptw.push_back(1); + i_vec_correct_num_solutions_spptw.push_back(2); + i_vec_correct_num_solutions_spptw.push_back(1); + i_vec_correct_num_solutions_spptw.push_back(1); + i_vec_correct_num_solutions_spptw.push_back(4); + i_vec_correct_num_solutions_spptw.push_back(1); + i_vec_correct_num_solutions_spptw.push_back(3); + i_vec_correct_num_solutions_spptw.push_back(0); + i_vec_correct_num_solutions_spptw.push_back(2); + i_vec_correct_num_solutions_spptw.push_back(3); + i_vec_correct_num_solutions_spptw.push_back(4); + i_vec_correct_num_solutions_spptw.push_back(1); + for (int s = 0; s < 10; ++s) + for (int t = 0; t < 10; ++t) + BOOST_TEST(static_cast< int >( + vec_vec_vec_vec_opt_solutions_spptw[s][t].size()) + == i_vec_correct_num_solutions_spptw[10 * s + t]); + + // one pareto-optimal solution + SPPRC_Example_Graph g2; + add_vertex(SPPRC_Example_Graph_Vert_Prop(0, 0, 1000000000), g2); + add_vertex(SPPRC_Example_Graph_Vert_Prop(1, 0, 1000000000), g2); + add_vertex(SPPRC_Example_Graph_Vert_Prop(2, 0, 1000000000), g2); + add_vertex(SPPRC_Example_Graph_Vert_Prop(3, 0, 1000000000), g2); + add_edge(0, 1, SPPRC_Example_Graph_Arc_Prop(0, 1, 1), g2); + add_edge(0, 2, SPPRC_Example_Graph_Arc_Prop(1, 2, 1), g2); + add_edge(1, 3, SPPRC_Example_Graph_Arc_Prop(2, 3, 1), g2); + add_edge(2, 3, SPPRC_Example_Graph_Arc_Prop(3, 1, 1), g2); + std::vector< graph_traits< SPPRC_Example_Graph >::edge_descriptor > + opt_solution; + spp_spptw_res_cont pareto_opt_rc; + r_c_shortest_paths(g2, get(&SPPRC_Example_Graph_Vert_Prop::num, g2), + get(&SPPRC_Example_Graph_Arc_Prop::num, g2), 0, 3, opt_solution, + pareto_opt_rc, spp_spptw_res_cont(0, 0), ref_spptw(), dominance_spptw(), + std::allocator< r_c_shortest_paths_label< SPPRC_Example_Graph, + spp_spptw_res_cont > >(), + default_r_c_shortest_paths_visitor()); + + BOOST_TEST(pareto_opt_rc.cost == 3); + + SPPRC_Example_Graph g3; + add_vertex(SPPRC_Example_Graph_Vert_Prop(0, 0, 1000), g3); + add_vertex(SPPRC_Example_Graph_Vert_Prop(1, 0, 1000), g3); + add_vertex(SPPRC_Example_Graph_Vert_Prop(2, 0, 974), g3); + add_vertex(SPPRC_Example_Graph_Vert_Prop(3, 0, 972), g3); + add_vertex(SPPRC_Example_Graph_Vert_Prop(4, 0, 967), g3); + add_vertex(SPPRC_Example_Graph_Vert_Prop(5, 678, 801), g3); + add_edge(0, 2, SPPRC_Example_Graph_Arc_Prop(0, 0, 16), g3); + add_edge(0, 3, SPPRC_Example_Graph_Arc_Prop(1, 0, 18), g3); + add_edge(0, 4, SPPRC_Example_Graph_Arc_Prop(2, 0, 23), g3); + add_edge(0, 5, SPPRC_Example_Graph_Arc_Prop(3, 0, 25), g3); + add_edge(2, 3, SPPRC_Example_Graph_Arc_Prop(4, 0, 33), g3); + add_edge(2, 4, SPPRC_Example_Graph_Arc_Prop(5, 0, 15), g3); + add_edge(2, 5, SPPRC_Example_Graph_Arc_Prop(6, 0, 33), g3); + add_edge(2, 1, SPPRC_Example_Graph_Arc_Prop(7, 0, 16), g3); + add_edge(3, 2, SPPRC_Example_Graph_Arc_Prop(8, 0, 33), g3); + add_edge(3, 4, SPPRC_Example_Graph_Arc_Prop(9, 0, 35), g3); + add_edge(3, 5, SPPRC_Example_Graph_Arc_Prop(10, 0, 21), g3); + add_edge(3, 1, SPPRC_Example_Graph_Arc_Prop(11, 0, 18), g3); + add_edge(4, 2, SPPRC_Example_Graph_Arc_Prop(12, 0, 15), g3); + add_edge(4, 3, SPPRC_Example_Graph_Arc_Prop(13, 0, 35), g3); + add_edge(4, 5, SPPRC_Example_Graph_Arc_Prop(14, 0, 25), g3); + add_edge(4, 1, SPPRC_Example_Graph_Arc_Prop(15, 0, 23), g3); + add_edge(5, 2, SPPRC_Example_Graph_Arc_Prop(16, 0, 33), g3); + add_edge(5, 3, SPPRC_Example_Graph_Arc_Prop(17, 0, 21), g3); + add_edge(5, 4, SPPRC_Example_Graph_Arc_Prop(18, 0, 25), g3); + add_edge(5, 1, SPPRC_Example_Graph_Arc_Prop(19, 0, 25), g3); + + std::vector< + std::vector< graph_traits< SPPRC_Example_Graph >::edge_descriptor > > + pareto_opt_marked_solutions; + std::vector< spp_spptw_marked_res_cont > + pareto_opt_marked_resource_containers; + + graph_traits< SPPRC_Example_Graph >::vertex_descriptor g3_source = 0, + g3_target = 1; + r_c_shortest_paths(g3, get(&SPPRC_Example_Graph_Vert_Prop::num, g3), + get(&SPPRC_Example_Graph_Arc_Prop::num, g3), g3_source, g3_target, + pareto_opt_marked_solutions, pareto_opt_marked_resource_containers, + spp_spptw_marked_res_cont(0, 0, 0), ref_spptw_marked(), + dominance_spptw_marked(), + std::allocator< r_c_shortest_paths_label< SPPRC_Example_Graph, + spp_spptw_marked_res_cont > >(), + default_r_c_shortest_paths_visitor()); + + BOOST_TEST(!pareto_opt_marked_solutions.empty()); + std::vector< std::vector< + graph_traits< SPPRC_Example_Graph >::edge_descriptor > >::const_iterator + path_it, + path_end_it; + for (path_it = pareto_opt_marked_solutions.begin(), + path_end_it = pareto_opt_marked_solutions.end(); + path_it != path_end_it; ++path_it) + { + const std::vector< + graph_traits< SPPRC_Example_Graph >::edge_descriptor >& path + = *path_it; + BOOST_TEST(!path.empty()); + + const graph_traits< SPPRC_Example_Graph >::edge_descriptor front + = path.front(); + BOOST_TEST(boost::target(front, g3) == g3_target); + + std::vector< graph_traits< SPPRC_Example_Graph >::edge_descriptor >:: + const_iterator edge_it, + edge_it_end; + graph_traits< SPPRC_Example_Graph >::edge_descriptor prev_edge = front; + + for (edge_it = path.begin() + 1, edge_it_end = path.end(); + edge_it != edge_it_end; ++edge_it) + { + graph_traits< SPPRC_Example_Graph >::edge_descriptor edge + = *edge_it; + + graph_traits< SPPRC_Example_Graph >::vertex_descriptor prev_end, + current_end; + prev_end = boost::source(prev_edge, g3); + current_end = boost::target(edge, g3); + BOOST_TEST(prev_end == current_end); + + prev_edge = edge; + } + + const graph_traits< SPPRC_Example_Graph >::edge_descriptor back + = path.back(); + BOOST_TEST(boost::source(back, g3) == g3_source); + } + + return boost::report_errors(); +} diff --git a/test/rcsp_custom_vertex_id.cpp b/test/rcsp_custom_vertex_id.cpp index c5e5ebf24..da61f71f2 100644 --- a/test/rcsp_custom_vertex_id.cpp +++ b/test/rcsp_custom_vertex_id.cpp @@ -113,8 +113,7 @@ int main() OptPath op; ParetoOpt ol; - r_c_shortest_paths(g, get(&VertexProperty::id, g), - get(&EdgeProperty::id, g), v1, v2, op, ol, ResourceCont(5), LabelExt(), + r_c_shortest_paths(g, get(&VertexProperty::id, g), v1, v2, op, ol, ResourceCont(5), LabelExt(), LabelDom(), allocator< r_c_shortest_paths_label< Graph, ResourceCont > >(), default_r_c_shortest_paths_visitor()); diff --git a/test/rcsp_custom_vertex_id_old.cpp b/test/rcsp_custom_vertex_id_old.cpp new file mode 100644 index 000000000..60b64764d --- /dev/null +++ b/test/rcsp_custom_vertex_id_old.cpp @@ -0,0 +1,123 @@ +//======================================================================= +// Copyright (c) 2013 Alberto Santini +// Author: Alberto Santini +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#include + +#ifdef BOOST_MSVC +// Without disabling this we get hard errors about initialialized pointers: +#pragma warning(disable : 4703) +#endif + +#include +#include +#include +#include +#include +#include + +using std::allocator; +using std::vector; +using namespace boost; + +class VertexProperty +{ +public: + int property1; + int property2; + int id; + VertexProperty() {} + VertexProperty(const int property1, const int property2) + : property1(property1), property2(property2) + { + } +}; + +class EdgeProperty +{ +public: + int cost; + int id; + EdgeProperty() {} + EdgeProperty(const int cost) : cost(cost) {} +}; + +typedef adjacency_list< listS, listS, bidirectionalS, VertexProperty, + EdgeProperty > + Graph; +typedef graph_traits< Graph >::vertex_descriptor Vertex; +typedef graph_traits< Graph >::edge_descriptor Edge; + +class ResourceCont +{ +public: + int res; + ResourceCont(const int res = 5) : res(res) {} + bool operator==(const ResourceCont& rc) const { return (res == rc.res); } + bool operator<(const ResourceCont& rc) const { return (res > rc.res); } +}; + +class LabelExt +{ +public: + bool operator()(const Graph& g, ResourceCont& rc, + const ResourceCont& old_rc, Edge e) const + { + rc.res = old_rc.res - g[e].cost; + return (rc.res > 0); + } +}; + +class LabelDom +{ +public: + bool operator()(const ResourceCont& rc1, const ResourceCont& rc2) const + { + return (rc1 == rc2 || rc1 < rc2); + } +}; + +int main() +{ + VertexProperty vp1(1, 1); + VertexProperty vp2(5, 9); + VertexProperty vp3(4, 3); + EdgeProperty e12(1); + EdgeProperty e23(2); + + Graph g; + + Vertex v1 = add_vertex(g); + g[v1] = vp1; + Vertex v2 = add_vertex(g); + g[v2] = vp2; + Vertex v3 = add_vertex(g); + g[v3] = vp3; + + add_edge(v1, v2, e12, g); + add_edge(v2, v3, e23, g); + + int index = 0; + BGL_FORALL_VERTICES(v, g, Graph) { g[v].id = index++; } + index = 0; + BGL_FORALL_EDGES(e, g, Graph) { g[e].id = index++; } + + typedef vector< vector< Edge > > OptPath; + typedef vector< ResourceCont > ParetoOpt; + + OptPath op; + ParetoOpt ol; + + r_c_shortest_paths(g, get(&VertexProperty::id, g), + v1, v2, op, ol, ResourceCont(5), LabelExt(), + LabelDom(), + allocator< r_c_shortest_paths_label< Graph, ResourceCont > >(), + default_r_c_shortest_paths_visitor()); + + return 0; +} diff --git a/test/rcsp_single_solution.cpp b/test/rcsp_single_solution.cpp index 765a7f373..f7b948019 100644 --- a/test/rcsp_single_solution.cpp +++ b/test/rcsp_single_solution.cpp @@ -75,13 +75,12 @@ struct extension_function { resource_container run_rcsp(const graph_type& graph, vertex_type source, vertex_type target) { const auto vertex_index_map = boost::get(boost::vertex_index, graph); - const auto edge_index_map = boost::get(boost::edge_all, graph); boost::default_r_c_shortest_paths_allocator label_allocator{}; path_type single_solution; resource_container single_resource(0, 0); const resource_container start_resource(0, 0); - boost::r_c_shortest_paths(graph, vertex_index_map, edge_index_map, source, target, single_solution, single_resource, + boost::r_c_shortest_paths(graph, vertex_index_map, source, target, single_solution, single_resource, start_resource, extension_function{}, dominance{}, label_allocator, boost::default_r_c_shortest_paths_visitor()); diff --git a/test/rcsp_single_solution_old.cpp b/test/rcsp_single_solution_old.cpp new file mode 100644 index 000000000..765a7f373 --- /dev/null +++ b/test/rcsp_single_solution_old.cpp @@ -0,0 +1,118 @@ +//======================================================================= +// Copyright (c) 2024 Andrea Cassioli +// Author: Andrea Cassioli +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#include +#include + +#include + +struct edge_prop { + edge_prop(int c, int t) : cost(c), time(t) {} + + int cost; + int time; +}; + +using graph_type = boost::adjacency_list; +using vertex_type = graph_type::vertex_descriptor; +using edge_type = graph_type::edge_descriptor; +using path_type = std::vector; + +class dominance +{ + public: + template + inline bool operator()(const C& res_cont_1, const C& res_cont_2) const { + return res_cont_1.cost <= res_cont_2.cost && res_cont_1.time <= res_cont_2.time; + } +}; + +struct resource_container +{ + resource_container(int c, int t) : cost(c), time(t) {} + + int cost; // minimise cost + int time; // a fake time constraints +}; + + +bool operator==( + const resource_container& res_cont_1, const resource_container& res_cont_2) +{ + return (res_cont_1.cost == res_cont_2.cost + && res_cont_1.time == res_cont_2.time); +} + +bool operator<( + const resource_container& res_cont_1, const resource_container& res_cont_2) +{ + if (res_cont_1.cost > res_cont_2.cost) + return false; + if (res_cont_1.cost == res_cont_2.cost) + return res_cont_1.time < res_cont_2.time; + return true; +} + +struct extension_function { + template + bool operator()(const GraphType& graph, + resource_container& new_cont, + const resource_container& old_cont, + const typename GraphType::edge_descriptor& edge) const { + new_cont = old_cont; + new_cont.cost = old_cont.cost + graph[edge].cost; + // here I could check tme constraint, but for this example does not matter + new_cont.time = old_cont.time + graph[edge].time; + return true; + } +}; + +resource_container run_rcsp(const graph_type& graph, vertex_type source, vertex_type target) { + const auto vertex_index_map = boost::get(boost::vertex_index, graph); + const auto edge_index_map = boost::get(boost::edge_all, graph); + boost::default_r_c_shortest_paths_allocator label_allocator{}; + + path_type single_solution; + resource_container single_resource(0, 0); + const resource_container start_resource(0, 0); + boost::r_c_shortest_paths(graph, vertex_index_map, edge_index_map, source, target, single_solution, single_resource, + start_resource, extension_function{}, dominance{}, label_allocator, + boost::default_r_c_shortest_paths_visitor()); + + return single_resource; +} + +int main() { + graph_type graph; + + /* + (1,0) (10, 1) + /-----> [A] ------\ + [s] [t] + \-----> [B] ------/ + (2, 1) (3,1) + + The shortest path is s->B->t with cost 5. + */ + + const auto s = boost::add_vertex("s", graph); + const auto A = boost::add_vertex("A", graph); + const auto B = boost::add_vertex("B", graph); + const auto t = boost::add_vertex("t", graph); + + boost::add_edge(s, A, edge_prop(1, 0), graph); + boost::add_edge(s, B, edge_prop(2, 1), graph); + boost::add_edge(A, t, edge_prop(10, 0), graph); + boost::add_edge(B, t, edge_prop(3, 1), graph); + + const auto solution_resource_container = run_rcsp(graph, s, t); + + BOOST_TEST(solution_resource_container.cost == 5); + return boost::report_errors(); +} From 7630d5cdf9738553ceb227f81cf43e9ef952b2fb Mon Sep 17 00:00:00 2001 From: Andrea Cassioli Date: Thu, 23 Jul 2026 22:21:04 +0200 Subject: [PATCH 3/3] modified jamfile --- example/Jamfile.v2 | 1 + 1 file changed, 1 insertion(+) diff --git a/example/Jamfile.v2 b/example/Jamfile.v2 index 1adf5c853..ed34f78d7 100644 --- a/example/Jamfile.v2 +++ b/example/Jamfile.v2 @@ -133,6 +133,7 @@ exe push-relable : push-relabel-eg.cpp ; run put-get-helper-eg.cpp ; run quick_tour.cpp ; run quick-tour.cpp ; +run r_c_shortest_paths_example_old.cpp ; run r_c_shortest_paths_example.cpp ; run read_graphviz.cpp /boost/graph//boost_graph ; exe read_write_dimacs : read_write_dimacs-eg.cpp ;