diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..36e77b53c --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +cube-fr.dot +cube.dot +disconnected-fr.dot +graphml_test_out.xml +kevin-bacon2.dat +random.dot +triangular-fr.dot +triangular-kk.dot diff --git a/doc/grid_graph_export_svg.sh b/doc/grid_graph_export_svg.sh index 03e7cb9c6..d12ea2169 100755 --- a/doc/grid_graph_export_svg.sh +++ b/doc/grid_graph_export_svg.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/bin/sh #======================================================================= # Copyright 2009 Trustees of Indiana University. @@ -16,4 +16,4 @@ inkscape --export-png grid_graph_unwrapped.png --export-id g3150 --export-id-onl inkscape --export-png grid_graph_wrapped.png grid_graph_unindexed.svg # Indexed, unwrapped -inkscape --export-png grid_graph_indexed.png grid_graph_indexed.svg \ No newline at end of file +inkscape --export-png grid_graph_indexed.png grid_graph_indexed.svg diff --git a/include/boost/graph/cycle_canceling.hpp b/include/boost/graph/cycle_canceling.hpp index 46a4b864c..bc7e69099 100644 --- a/include/boost/graph/cycle_canceling.hpp +++ b/include/boost/graph/cycle_canceling.hpp @@ -1,6 +1,6 @@ //======================================================================= // Copyright 2013 University of Warsaw. -// Authors: Piotr Wygocki +// Authors: Piotr Wygocki // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -12,7 +12,7 @@ // by Ahuja, Magnanti, Orlin. #ifndef BOOST_GRAPH_CYCLE_CANCELING_HPP -#define BOOST_GRAPH_CYCLE_CANCELING_HPP +#define BOOST_GRAPH_CYCLE_CANCELING_HPP #include @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include @@ -32,11 +31,11 @@ namespace boost { namespace detail { template -class RecordEdgeMapAndCycleVertex +class RecordEdgeMapAndCycleVertex : public bellman_visitor > { typedef edge_predecessor_recorder PredRec; public: - RecordEdgeMapAndCycleVertex(PredEdgeMap pred, Vertex & v) : + RecordEdgeMapAndCycleVertex(PredEdgeMap pred, Vertex & v) : bellman_visitor(PredRec(pred)), m_v(v), m_pred(pred) {} template @@ -63,27 +62,27 @@ template > ResGraph; ResGraph gres = detail::residual_graph(g, residual_capacity); - + typedef graph_traits ResGTraits; typedef graph_traits GTraits; typedef typename ResGTraits::edge_descriptor edge_descriptor; typedef typename ResGTraits::vertex_descriptor vertex_descriptor; - + typename GTraits::vertices_size_type N = num_vertices(g); - + BGL_FORALL_VERTICES_T(v, g, Graph) { put(pred, v, edge_descriptor()); put(distance, v, 0); } vertex_descriptor cycleStart; - while(!bellman_ford_shortest_paths(gres, N, + while(!bellman_ford_shortest_paths(gres, N, weight_map(weight). distance_map(distance). visitor(detail::RecordEdgeMapAndCycleVertex(pred, cycleStart)))) { detail::augment(g, cycleStart, cycleStart, pred, residual_capacity, rev); - + BGL_FORALL_VERTICES_T(v, g, Graph) { put(pred, v, edge_descriptor()); put(distance, v, 0); @@ -97,7 +96,7 @@ namespace detail { template void cycle_canceling_dispatch2( - const Graph &g, + const Graph &g, Weight weight, Reversed rev, ResidualCapacity residual_capacity, @@ -110,7 +109,7 @@ void cycle_canceling_dispatch2( //setting default distance map template void cycle_canceling_dispatch2( - Graph &g, + Graph &g, Weight weight, Reversed rev, ResidualCapacity residual_capacity, @@ -121,27 +120,27 @@ void cycle_canceling_dispatch2( std::vector d_map(num_vertices(g)); - cycle_canceling(g, weight, rev, residual_capacity, pred, + cycle_canceling(g, weight, rev, residual_capacity, pred, make_iterator_property_map(d_map.begin(), choose_const_pmap(get_param(params, vertex_index), g, vertex_index))); } template void cycle_canceling_dispatch1( - Graph &g, - Weight weight, + Graph &g, + Weight weight, Reversed rev, ResidualCapacity residual_capacity, Pred pred, const bgl_named_params& params) { - cycle_canceling_dispatch2(g, weight, rev,residual_capacity, pred, + cycle_canceling_dispatch2(g, weight, rev,residual_capacity, pred, get_param(params, vertex_distance), params); } //setting default predecessors map template void cycle_canceling_dispatch1( - Graph &g, - Weight weight, + Graph &g, + Weight weight, Reversed rev, ResidualCapacity residual_capacity, param_not_found, @@ -151,7 +150,7 @@ void cycle_canceling_dispatch1( cycle_canceling_dispatch2(g, weight, rev, residual_capacity, make_iterator_property_map(p_map.begin(), choose_const_pmap(get_param(params, vertex_index), g, vertex_index)), - get_param(params, vertex_distance), params); + get_param(params, vertex_distance), params); } }//detail @@ -159,12 +158,12 @@ void cycle_canceling_dispatch1( template void cycle_canceling(Graph &g, const bgl_named_params& params) { - cycle_canceling_dispatch1(g, + cycle_canceling_dispatch1(g, choose_const_pmap(get_param(params, edge_weight), g, edge_weight), choose_const_pmap(get_param(params, edge_reverse), g, edge_reverse), - choose_pmap(get_param(params, edge_residual_capacity), + choose_pmap(get_param(params, edge_residual_capacity), g, edge_residual_capacity), - get_param(params, vertex_predecessor), + get_param(params, vertex_predecessor), params); } @@ -178,4 +177,3 @@ void cycle_canceling(Graph &g) { } #endif /* BOOST_GRAPH_CYCLE_CANCELING_HPP */ - diff --git a/include/boost/graph/detail/adjacency_list.hpp b/include/boost/graph/detail/adjacency_list.hpp index 6fb497d7e..01d400ffd 100644 --- a/include/boost/graph/detail/adjacency_list.hpp +++ b/include/boost/graph/detail/adjacency_list.hpp @@ -267,7 +267,7 @@ namespace boost { : Base(static_cast< Base const& >(x)), m_property(const_cast(x).m_property) { } self& operator=(const self& x) { // NOTE: avoid 'Base::operator=(x);' broken on SGI MIPSpro (bug 55771 of Mozilla). - static_cast(*this) = static_cast< Base const& >(x); + static_cast(*this) = static_cast< Base const& >(x); m_property = const_cast(x).m_property; return *this; } @@ -277,7 +277,7 @@ namespace boost { : Base(static_cast< Base&& >(x)), m_property(std::move(x.m_property)) { } self& operator=(self&& x) { // NOTE: avoid 'Base::operator=(x);' broken on SGI MIPSpro (bug 55771 of Mozilla). - static_cast(*this) = static_cast< Base&& >(x); + static_cast(*this) = static_cast< Base&& >(x); m_property = std::move(x.m_property); return *this; } @@ -2051,16 +2051,15 @@ namespace boost { if ((*ei).get_target() > u) --(*ei).get_target(); } + template inline void reindex_edge_list(EdgeList& el, vertex_descriptor u, boost::disallow_parallel_edge_tag) { - typename EdgeList::iterator ei = el.begin(), e_end = el.end(); - while (ei != e_end) { - typename EdgeList::value_type ce = *ei; - ++ei; - if (ce.get_target() > u) { + for(typename EdgeList::iterator ei = el.begin(); ei != el.end(); ++ei) { + if (ei->get_target() > u) { + typename EdgeList::value_type ce = *ei; el.erase(ce); --ce.get_target(); el.insert(ce); diff --git a/include/boost/graph/dijkstra_shortest_paths.hpp b/include/boost/graph/dijkstra_shortest_paths.hpp index 10e40f828..f6833f6e1 100644 --- a/include/boost/graph/dijkstra_shortest_paths.hpp +++ b/include/boost/graph/dijkstra_shortest_paths.hpp @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include @@ -53,18 +52,13 @@ namespace boost { * @param old_distance the previous distance to @p vertex */ template - inline void + inline void dijkstra_queue_update(Buffer& Q, Vertex vertex, DistanceType old_distance) { (void)old_distance; Q.update(vertex); } -#ifdef BOOST_GRAPH_DIJKSTRA_TESTING - // This is a misnomer now: it now just refers to the "default heap", which is - // currently d-ary (d=4) but can be changed by a #define. - static bool dijkstra_relaxed_heap = true; -#endif template struct DijkstraVisitorConcept { @@ -187,7 +181,7 @@ namespace boost { // The test here is equivalent to e_weight < 0 if m_combine has a // cancellation law, but always returns false when m_combine is a // projection operator. - if (m_compare(m_combine(m_zero, get(m_weight, e)), m_zero)) + if (m_compare(m_combine(m_zero, get(m_weight, e)), m_zero)) boost::throw_exception(negative_edge()); // End of test for negative-weight edges. @@ -345,25 +339,7 @@ namespace boost { typedef typename graph_traits::vertex_descriptor Vertex; -#ifdef BOOST_GRAPH_DIJKSTRA_TESTING - if (!dijkstra_relaxed_heap) { - typedef mutable_queue, IndirectCmp, IndexMap> - MutableQueue; - - MutableQueue Q(num_vertices(g), icmp, index_map); - detail::dijkstra_bfs_visitor - bfs_vis(vis, Q, weight, predecessor, distance, combine, compare, zero); - - breadth_first_visit(g, s_begin, s_end, Q, bfs_vis, color); - return; - } -#endif // BOOST_GRAPH_DIJKSTRA_TESTING - -#ifdef BOOST_GRAPH_DIJKSTRA_USE_RELAXED_HEAP - typedef relaxed_heap MutableQueue; - MutableQueue Q(num_vertices(g), icmp, index_map); -#else // Now the default: use a d-ary heap + // Now the default: use a d-ary heap boost::scoped_array index_in_heap_map_holder; typedef detail::vertex_property_map_generator @@ -374,7 +350,6 @@ namespace boost { typedef d_ary_heap_indirect MutableQueue; MutableQueue Q(distance, index_in_heap, compare); -#endif // Relaxed heap detail::dijkstra_bfs_visitor @@ -406,7 +381,7 @@ namespace boost { template inline void dijkstra_shortest_paths @@ -429,7 +404,7 @@ namespace boost { template inline void dijkstra_shortest_paths diff --git a/include/boost/graph/dijkstra_shortest_paths_no_color_map.hpp b/include/boost/graph/dijkstra_shortest_paths_no_color_map.hpp index b1a9ef589..eb96c0d88 100644 --- a/include/boost/graph/dijkstra_shortest_paths_no_color_map.hpp +++ b/include/boost/graph/dijkstra_shortest_paths_no_color_map.hpp @@ -13,7 +13,6 @@ #include #include -#include #include #include #include @@ -41,19 +40,12 @@ namespace boost { { typedef typename graph_traits::vertex_descriptor Vertex; typedef typename property_traits::value_type Distance; - + typedef indirect_cmp DistanceIndirectCompare; DistanceIndirectCompare distance_indirect_compare(distance_map, distance_compare); - - // Choose vertex queue type -#if BOOST_GRAPH_DIJKSTRA_USE_RELAXED_HEAP - typedef relaxed_heap - VertexQueue; - VertexQueue vertex_queue(num_vertices(graph), - distance_indirect_compare, - index_map); -#else + + // Default - use d-ary heap (d = 4) typedef detail::vertex_property_map_generator @@ -62,54 +54,53 @@ namespace boost { typedef d_ary_heap_indirect VertexQueue; - + boost::scoped_array index_in_heap_map_holder; IndexInHeapMap index_in_heap = IndexInHeapMapHelper::build(graph, index_map, - index_in_heap_map_holder); + index_in_heap_map_holder); VertexQueue vertex_queue(distance_map, index_in_heap, distance_compare); -#endif - + // Add vertex to the queue vertex_queue.push(start_vertex); - + // Starting vertex will always be the first discovered vertex visitor.discover_vertex(start_vertex, graph); - + while (!vertex_queue.empty()) { Vertex min_vertex = vertex_queue.top(); vertex_queue.pop(); - + visitor.examine_vertex(min_vertex, graph); - + // Check if any other vertices can be reached Distance min_vertex_distance = get(distance_map, min_vertex); - + if (!distance_compare(min_vertex_distance, distance_infinity)) { // This is the minimum vertex, so all other vertices are unreachable return; } - + // Examine neighbors of min_vertex BGL_FORALL_OUTEDGES_T(min_vertex, current_edge, graph, Graph) { visitor.examine_edge(current_edge, graph); - + // Check if the edge has a negative weight if (distance_compare(get(weight_map, current_edge), distance_zero)) { boost::throw_exception(negative_edge()); } - + // Extract the neighboring vertex and get its distance Vertex neighbor_vertex = target(current_edge, graph); Distance neighbor_vertex_distance = get(distance_map, neighbor_vertex); - bool is_neighbor_undiscovered = + bool is_neighbor_undiscovered = !distance_compare(neighbor_vertex_distance, distance_infinity); // Attempt to relax the edge bool was_edge_relaxed = relax(current_edge, graph, weight_map, predecessor_map, distance_map, distance_weight_combine, distance_compare); - + if (was_edge_relaxed) { visitor.edge_relaxed(current_edge, graph); if (is_neighbor_undiscovered) { @@ -121,9 +112,9 @@ namespace boost { } else { visitor.edge_not_relaxed(current_edge, graph); } - + } // end out edge iteration - + visitor.finish_vertex(min_vertex, graph); } // end while queue not empty } @@ -150,17 +141,17 @@ namespace boost { // Initialize vertices BGL_FORALL_VERTICES_T(current_vertex, graph, Graph) { visitor.initialize_vertex(current_vertex, graph); - + // Default all distances to infinity put(distance_map, current_vertex, distance_infinity); - + // Default all vertex predecessors to the vertex itself put(predecessor_map, current_vertex, current_vertex); } - + // Set distance for start_vertex to zero put(distance_map, start_vertex, distance_zero); - + // Pass everything on to the no_init version dijkstra_shortest_paths_no_color_map_no_init(graph, start_vertex, predecessor_map, distance_map, weight_map, @@ -216,7 +207,7 @@ namespace boost { typedef typename property_traits::value_type DistanceType; typename std::vector::size_type vertex_count = is_default_param(distance_map) ? num_vertices(graph) : 1; - + std::vector default_distance_map(vertex_count); detail::dijkstra_no_color_map_dispatch2 diff --git a/include/boost/graph/maximum_adjacency_search.hpp b/include/boost/graph/maximum_adjacency_search.hpp index e27a7a048..558c89161 100644 --- a/include/boost/graph/maximum_adjacency_search.hpp +++ b/include/boost/graph/maximum_adjacency_search.hpp @@ -146,10 +146,10 @@ namespace boost { // start traversing the graph //vertex_descriptor s, t; - weight_type w; + //weight_type w; while (!pq.empty()) { // while PQ \neq {} do const vertex_descriptor u = pq.top(); // u = extractmax(PQ) - w = get(keys, u); vis.start_vertex(u, g); + get(keys, u); vis.start_vertex(u, g); pq.pop(); // vis.start_vertex(u, g); BGL_FORALL_OUTEDGES_T(u, e, g, Graph) { // foreach (u, v) \in E do @@ -218,9 +218,9 @@ maximum_adjacency_search(const Graph& g, WeightMap weights, MASVisitor vis, cons struct mas_dispatch { typedef void result_type; template - static result_type apply(const Graph& g, - //const bgl_named_params& params, - const ArgPack& params, + static result_type apply(const Graph& g, + //const bgl_named_params& params, + const ArgPack& params, WeightMap w) { using namespace boost::graph::keywords; @@ -249,8 +249,8 @@ maximum_adjacency_search(const Graph& g, WeightMap weights, MASVisitor vis, cons typedef void result_type; template - static result_type apply(const Graph& g, - const ArgPack& params, + static result_type apply(const Graph& g, + const ArgPack& params, param_not_found) { using namespace boost::graph::keywords; diff --git a/include/boost/graph/r_c_shortest_paths.hpp b/include/boost/graph/r_c_shortest_paths.hpp index 7e490fc7d..f047e0f7c 100644 --- a/include/boost/graph/r_c_shortest_paths.hpp +++ b/include/boost/graph/r_c_shortest_paths.hpp @@ -2,7 +2,7 @@ // Copyright Michael Drexl 2005, 2006. // Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at +// (See accompanying file LICENSE_1_0.txt or copy at // http://boost.org/LICENSE_1_0.txt) #ifndef BOOST_GRAPH_R_C_SHORTEST_PATHS_HPP @@ -13,6 +13,8 @@ #include #include +#include +#include #include #include #include @@ -21,25 +23,23 @@ namespace boost { // r_c_shortest_paths_label struct template -struct r_c_shortest_paths_label +struct r_c_shortest_paths_label : public boost::enable_shared_from_this > { r_c_shortest_paths_label - ( const unsigned long n, - const Resource_Container& rc = Resource_Container(), - const r_c_shortest_paths_label* const pl = 0, - const typename graph_traits::edge_descriptor& ed = - graph_traits::edge_descriptor(), - const typename graph_traits::vertex_descriptor& vd = - graph_traits::vertex_descriptor() ) - : num( n ), - cumulated_resource_consumption( rc ), - p_pred_label( pl ), - pred_edge( ed ), - resident_vertex( vd ), - b_is_dominated( false ), - b_is_processed( false ), - b_is_valid( true ) + ( const unsigned long n, + const Resource_Container& rc = Resource_Container(), + const boost::shared_ptr > pl = boost::shared_ptr >(), + const typename graph_traits::edge_descriptor& ed = graph_traits::edge_descriptor(), + const typename graph_traits::vertex_descriptor& vd = graph_traits::vertex_descriptor() ) + : num( n ), + cumulated_resource_consumption( rc ), + p_pred_label( pl ), + pred_edge( ed ), + resident_vertex( vd ), + b_is_dominated( false ), + b_is_processed( false ) {} + r_c_shortest_paths_label& operator=( const r_c_shortest_paths_label& other ) { if( this == &other ) @@ -50,179 +50,153 @@ struct r_c_shortest_paths_label } const unsigned long num; Resource_Container cumulated_resource_consumption; - const r_c_shortest_paths_label* const p_pred_label; + const boost::shared_ptr > p_pred_label; const typename graph_traits::edge_descriptor pred_edge; const typename graph_traits::vertex_descriptor resident_vertex; bool b_is_dominated; bool b_is_processed; - bool b_is_valid; }; // r_c_shortest_paths_label template inline bool operator== -( const r_c_shortest_paths_label& l1, +( const r_c_shortest_paths_label& l1, const r_c_shortest_paths_label& l2 ) { - assert (l1.b_is_valid && l2.b_is_valid); - return + return l1.cumulated_resource_consumption == l2.cumulated_resource_consumption; } template inline bool operator!= -( const r_c_shortest_paths_label& l1, +( const r_c_shortest_paths_label& l1, const r_c_shortest_paths_label& l2 ) { - assert (l1.b_is_valid && l2.b_is_valid); - return + return !( l1 == l2 ); } template inline bool operator< -( const r_c_shortest_paths_label& l1, +( const r_c_shortest_paths_label& l1, const r_c_shortest_paths_label& l2 ) { - assert (l1.b_is_valid && l2.b_is_valid); - return + return l1.cumulated_resource_consumption < l2.cumulated_resource_consumption; } template inline bool operator> -( const r_c_shortest_paths_label& l1, +( const r_c_shortest_paths_label& l1, const r_c_shortest_paths_label& l2 ) { - assert (l1.b_is_valid && l2.b_is_valid); - return + return l2.cumulated_resource_consumption < l1.cumulated_resource_consumption; } template inline bool operator<= -( const r_c_shortest_paths_label& l1, +( const r_c_shortest_paths_label& l1, const r_c_shortest_paths_label& l2 ) { - assert (l1.b_is_valid && l2.b_is_valid); - return + return l1 < l2 || l1 == l2; } template inline bool operator>= -( const r_c_shortest_paths_label& l1, +( const r_c_shortest_paths_label& l1, const r_c_shortest_paths_label& l2 ) { - assert (l1.b_is_valid && l2.b_is_valid); return l2 < l1 || l1 == l2; } -namespace detail { +template +inline bool operator< + ( const boost::shared_ptr > &t, + const boost::shared_ptr > &u) { + return *t < *u; +} -// ks_smart_pointer class -// from: -// Kuhlins, S.; Schader, M. (1999): -// Die C++-Standardbibliothek -// Springer, Berlin -// p. 333 f. -template -class ks_smart_pointer -{ -public: - ks_smart_pointer( T* ptt = 0 ) : pt( ptt ) {} - ks_smart_pointer( const ks_smart_pointer& other ) : pt( other.pt ) {} - ks_smart_pointer& operator=( const ks_smart_pointer& other ) - { pt = other.pt; return *this; } - ~ks_smart_pointer() {} - T& operator*() const { return *pt; } - T* operator->() const { return pt; } - T* get() const { return pt; } - operator T*() const { return pt; } - friend bool operator==( const ks_smart_pointer& t, - const ks_smart_pointer& u ) - { return *t.pt == *u.pt; } - friend bool operator!=( const ks_smart_pointer& t, - const ks_smart_pointer& u ) - { return *t.pt != *u.pt; } - friend bool operator<( const ks_smart_pointer& t, - const ks_smart_pointer& u ) - { return *t.pt < *u.pt; } - friend bool operator>( const ks_smart_pointer& t, - const ks_smart_pointer& u ) - { return *t.pt > *u.pt; } - friend bool operator<=( const ks_smart_pointer& t, - const ks_smart_pointer& u ) - { return *t.pt <= *u.pt; } - friend bool operator>=( const ks_smart_pointer& t, - const ks_smart_pointer& u ) - { return *t.pt >= *u.pt; } -private: - T* pt; -}; // ks_smart_pointer +template +inline bool operator<=( const boost::shared_ptr > &t, + const boost::shared_ptr > &u ) { + return *t <= *u; +} +template +inline bool operator> + ( + const boost::shared_ptr > &t, + const boost::shared_ptr > &u ) { + return *t > *u; +} + +template +inline bool operator>= + ( + const boost::shared_ptr > &t, + const boost::shared_ptr > &u) { + return *t >= *u; +} + +namespace detail { // r_c_shortest_paths_dispatch function (body/implementation) -template void r_c_shortest_paths_dispatch -( const Graph& g, - const VertexIndexMap& vertex_index_map, - const EdgeIndexMap& /*edge_index_map*/, - typename graph_traits::vertex_descriptor s, - typename graph_traits::vertex_descriptor t, +( const Graph& g, + const VertexIndexMap& vertex_index_map, + const EdgeIndexMap& /*edge_index_map*/, + typename graph_traits::vertex_descriptor s, + typename graph_traits::vertex_descriptor t, // each inner vector corresponds to a pareto-optimal path std::vector ::edge_descriptor> >& pareto_optimal_solutions, + ::edge_descriptor> >& pareto_optimal_solutions, std::vector - & pareto_optimal_resource_containers, - bool b_all_pareto_optimal_solutions, - // to initialize the first label/resource container + & pareto_optimal_resource_containers, + bool b_all_pareto_optimal_solutions, + // to initialize the first label/resource container // and to carry the type information - const Resource_Container& rc, - Resource_Extension_Function& ref, - Dominance_Function& dominance, + const Resource_Container& rc, + Resource_Extension_Function& ref, + Dominance_Function& dominance, // to specify the memory management strategy for the labels - Label_Allocator /*la*/, + Label_Allocator /*la*/, Visitor vis ) { pareto_optimal_resource_containers.clear(); pareto_optimal_solutions.clear(); size_t i_label_num = 0; - typedef - typename + typedef + typename Label_Allocator::template rebind >::other LAlloc; LAlloc l_alloc; - typedef - ks_smart_pointer - > Splabel; - std::priority_queue, std::greater > + typedef + boost::shared_ptr > Splabel; + std::priority_queue, std::greater > unprocessed_labels; bool b_feasible = true; - r_c_shortest_paths_label* first_label = - l_alloc.allocate( 1 ); - l_alloc.construct - ( first_label, - r_c_shortest_paths_label - ( i_label_num++, - rc, - 0, - typename graph_traits:: - edge_descriptor(), - s ) ); - - Splabel splabel_first_label = Splabel( first_label ); + Splabel splabel_first_label = boost::allocate_shared >( + l_alloc, + i_label_num++, + rc, + boost::shared_ptr >(), + typename graph_traits::edge_descriptor(), + s ); + unprocessed_labels.push( splabel_first_label ); std::vector > vec_vertex_labels_data( num_vertices( g ) ); iterator_property_map >::iterator, @@ -230,7 +204,7 @@ void r_c_shortest_paths_dispatch vec_vertex_labels(vec_vertex_labels_data.begin(), vertex_index_map); vec_vertex_labels[s].push_back( splabel_first_label ); typedef - std::vector::iterator> + std::vector::iterator> vec_last_valid_positions_for_dominance_data_type; vec_last_valid_positions_for_dominance_data_type vec_last_valid_positions_for_dominance_data( num_vertices( g ) ); @@ -247,7 +221,7 @@ void r_c_shortest_paths_dispatch iterator_property_map::iterator, VertexIndexMap> vec_last_valid_index_for_dominance (vec_last_valid_index_for_dominance_data.begin(), vertex_index_map); - std::vector + std::vector b_vec_vertex_already_checked_for_dominance_data( num_vertices( g ), false ); iterator_property_map::iterator, VertexIndexMap> b_vec_vertex_already_checked_for_dominance @@ -257,42 +231,39 @@ void r_c_shortest_paths_dispatch while( !unprocessed_labels.empty() && vis.on_enter_loop(unprocessed_labels, g) ) { Splabel cur_label = unprocessed_labels.top(); - assert (cur_label->b_is_valid); unprocessed_labels.pop(); vis.on_label_popped( *cur_label, g ); - // an Splabel object in unprocessed_labels and the respective Splabel - // object in the respective list of vec_vertex_labels share their + // an Splabel object in unprocessed_labels and the respective Splabel + // object in the respective list of vec_vertex_labels share their // embedded r_c_shortest_paths_label object - // to avoid memory leaks, dominated - // r_c_shortest_paths_label objects are marked and deleted when popped - // from unprocessed_labels, as they can no longer be deleted at the end of - // the function; only the Splabel object in unprocessed_labels still + // to avoid memory leaks, dominated + // r_c_shortest_paths_label objects are marked and deleted when popped + // from unprocessed_labels, as they can no longer be deleted at the end of + // the function; only the Splabel object in unprocessed_labels still // references the r_c_shortest_paths_label object - // this is also for efficiency, because the else branch is executed only - // if there is a chance that extending the - // label leads to new undominated labels, which in turn is possible only + // this is also for efficiency, because the else branch is executed only + // if there is a chance that extending the + // label leads to new undominated labels, which in turn is possible only // if the label to be extended is undominated - assert (cur_label->b_is_valid); if( !cur_label->b_is_dominated ) { typename boost::graph_traits::vertex_descriptor i_cur_resident_vertex = cur_label->resident_vertex; - std::list& list_labels_cur_vertex = + std::list& list_labels_cur_vertex = get(vec_vertex_labels, i_cur_resident_vertex); - if( list_labels_cur_vertex.size() >= 2 - && vec_last_valid_index_for_dominance[i_cur_resident_vertex] + if( list_labels_cur_vertex.size() >= 2 + && vec_last_valid_index_for_dominance[i_cur_resident_vertex] < list_labels_cur_vertex.size() ) { - typename std::list::iterator outer_iter = + typename std::list::iterator outer_iter = list_labels_cur_vertex.begin(); bool b_outer_iter_at_or_beyond_last_valid_pos_for_dominance = false; while( outer_iter != list_labels_cur_vertex.end() ) { Splabel cur_outer_splabel = *outer_iter; - assert (cur_outer_splabel->b_is_valid); typename std::list::iterator inner_iter = outer_iter; - if( !b_outer_iter_at_or_beyond_last_valid_pos_for_dominance - && outer_iter == + if( !b_outer_iter_at_or_beyond_last_valid_pos_for_dominance + && outer_iter == get(vec_last_valid_positions_for_dominance, i_cur_resident_vertex) ) b_outer_iter_at_or_beyond_last_valid_pos_for_dominance = true; @@ -303,7 +274,7 @@ void r_c_shortest_paths_dispatch } else { - inner_iter = + inner_iter = get(vec_last_valid_positions_for_dominance, i_cur_resident_vertex); ++inner_iter; @@ -312,9 +283,8 @@ void r_c_shortest_paths_dispatch while( inner_iter != list_labels_cur_vertex.end() ) { Splabel cur_inner_splabel = *inner_iter; - assert (cur_inner_splabel->b_is_valid); if( dominance( cur_outer_splabel-> - cumulated_resource_consumption, + cumulated_resource_consumption, cur_inner_splabel-> cumulated_resource_consumption ) ) { @@ -323,9 +293,7 @@ void r_c_shortest_paths_dispatch list_labels_cur_vertex.erase( buf ); if( cur_inner_splabel->b_is_processed ) { - cur_inner_splabel->b_is_valid = false; - l_alloc.destroy( cur_inner_splabel.get() ); - l_alloc.deallocate( cur_inner_splabel.get(), 1 ); + cur_inner_splabel.reset(); } else cur_inner_splabel->b_is_dominated = true; @@ -334,7 +302,7 @@ void r_c_shortest_paths_dispatch else ++inner_iter; if( dominance( cur_inner_splabel-> - cumulated_resource_consumption, + cumulated_resource_consumption, cur_outer_splabel-> cumulated_resource_consumption ) ) { @@ -342,12 +310,9 @@ void r_c_shortest_paths_dispatch ++outer_iter; list_labels_cur_vertex.erase( buf ); b_outer_iter_erased = true; - assert (cur_outer_splabel->b_is_valid); if( cur_outer_splabel->b_is_processed ) { - cur_outer_splabel->b_is_valid = false; - l_alloc.destroy( cur_outer_splabel.get() ); - l_alloc.deallocate( cur_outer_splabel.get(), 1 ); + cur_outer_splabel.reset(); } else cur_outer_splabel->b_is_dominated = true; @@ -369,28 +334,22 @@ void r_c_shortest_paths_dispatch list_labels_cur_vertex.size() - 1); } } - assert (b_all_pareto_optimal_solutions || cur_label->b_is_valid); if( !b_all_pareto_optimal_solutions && cur_label->resident_vertex == t ) { // the devil don't sleep if( cur_label->b_is_dominated ) { - cur_label->b_is_valid = false; - l_alloc.destroy( cur_label.get() ); - l_alloc.deallocate( cur_label.get(), 1 ); + cur_label.reset(); } while( unprocessed_labels.size() ) { Splabel l = unprocessed_labels.top(); - assert (l->b_is_valid); unprocessed_labels.pop(); - // delete only dominated labels, because nondominated labels are + // delete only dominated labels, because nondominated labels are // deleted at the end of the function if( l->b_is_dominated ) { - l->b_is_valid = false; - l_alloc.destroy( l.get() ); - l_alloc.deallocate( l.get(), 1 ); + l.reset(); } } break; @@ -399,56 +358,45 @@ void r_c_shortest_paths_dispatch { cur_label->b_is_processed = true; vis.on_label_not_dominated( *cur_label, g ); - typename graph_traits::vertex_descriptor cur_vertex = + typename graph_traits::vertex_descriptor cur_vertex = cur_label->resident_vertex; typename graph_traits::out_edge_iterator oei, oei_end; - for( boost::tie( oei, oei_end ) = out_edges( cur_vertex, g ); - oei != oei_end; + for( boost::tie( oei, oei_end ) = out_edges( cur_vertex, g ); + oei != oei_end; ++oei ) { b_feasible = true; - r_c_shortest_paths_label* new_label = - l_alloc.allocate( 1 ); - l_alloc.construct( new_label, - r_c_shortest_paths_label - - ( i_label_num++, - cur_label->cumulated_resource_consumption, - cur_label.get(), - *oei, - target( *oei, g ) ) ); - b_feasible = - ref( g, - new_label->cumulated_resource_consumption, - new_label->p_pred_label->cumulated_resource_consumption, + Splabel new_label = boost::allocate_shared >( + l_alloc, + i_label_num++, + cur_label->cumulated_resource_consumption, + cur_label, + *oei, + target( *oei, g ) ); + b_feasible = + ref( g, + new_label->cumulated_resource_consumption, + new_label->p_pred_label->cumulated_resource_consumption, new_label->pred_edge ); if( !b_feasible ) { vis.on_label_not_feasible( *new_label, g ); - new_label->b_is_valid = false; - l_alloc.destroy( new_label ); - l_alloc.deallocate( new_label, 1 ); + new_label.reset(); } else { - const r_c_shortest_paths_label& - ref_new_label = *new_label; - vis.on_label_feasible( ref_new_label, g ); - Splabel new_sp_label( new_label ); - vec_vertex_labels[new_sp_label->resident_vertex]. - push_back( new_sp_label ); - unprocessed_labels.push( new_sp_label ); + vis.on_label_feasible( *new_label, g ); + vec_vertex_labels[new_label->resident_vertex]. + push_back( new_label ); + unprocessed_labels.push( new_label ); } } } else { - assert (cur_label->b_is_valid); vis.on_label_dominated( *cur_label, g ); - cur_label->b_is_valid = false; - l_alloc.destroy( cur_label.get() ); - l_alloc.deallocate( cur_label.get(), 1 ); + cur_label.reset(); } } std::list dsplabels = get(vec_vertex_labels, t); @@ -459,18 +407,31 @@ void r_c_shortest_paths_dispatch { for( ; csi != csi_end; ++csi ) { - std::vector::edge_descriptor> + std::vector::edge_descriptor> cur_pareto_optimal_path; - const r_c_shortest_paths_label* p_cur_label = - (*csi).get(); - assert (p_cur_label->b_is_valid); + boost::shared_ptr > p_cur_label = *csi; pareto_optimal_resource_containers. push_back( p_cur_label->cumulated_resource_consumption ); while( p_cur_label->num != 0 ) { cur_pareto_optimal_path.push_back( p_cur_label->pred_edge ); p_cur_label = p_cur_label->p_pred_label; - assert (p_cur_label->b_is_valid); + + // assertion b_is_valid beyond this point is not correct if the domination function + // requires resource levels to be strictly greater than existing values + // + // Example + // Customers + // id min_arrival max_departure + // 2 0 974 + // 3 0 972 + // 4 0 964 + // 5 678 801 + // + // Path A: 2-3-4-5 (times: 0-16-49-84-678) + // Path B: 3-2-4-5 (times: 0-18-51-62-678) + // The partial path 3-2-4 dominates the other partial path 2-3-4, + // though the path 3-2-4-5 does not strictly dominate the path 2-3-4-5 } pareto_optimal_solutions.push_back( cur_pareto_optimal_path ); if( !b_all_pareto_optimal_solutions ) @@ -479,14 +440,12 @@ void r_c_shortest_paths_dispatch } BGL_FORALL_VERTICES_T(i, g, Graph) { - const std::list& list_labels_cur_vertex = vec_vertex_labels[i]; - csi_end = list_labels_cur_vertex.end(); - for( csi = list_labels_cur_vertex.begin(); csi != csi_end; ++csi ) + std::list& list_labels_cur_vertex = vec_vertex_labels[i]; + typename std::list::iterator si = list_labels_cur_vertex.begin(); + const typename std::list::iterator si_end = list_labels_cur_vertex.end(); + for(; si != si_end; ++si ) { - assert ((*csi)->b_is_valid); - (*csi)->b_is_valid = false; - l_alloc.destroy( (*csi).get() ); - l_alloc.deallocate( (*csi).get(), 1 ); + (*si).reset(); } } } // r_c_shortest_paths_dispatch @@ -506,13 +465,13 @@ struct default_r_c_shortest_paths_visitor void on_label_dominated( const Label&, const Graph& ) {} template void on_label_not_dominated( const Label&, const Graph& ) {} - template + template bool on_enter_loop(const Queue& queue, const Graph& graph) {return true;} }; // default_r_c_shortest_paths_visitor // default_r_c_shortest_paths_allocator -typedef +typedef std::allocator default_r_c_shortest_paths_allocator; // default_r_c_shortest_paths_allocator @@ -521,93 +480,93 @@ typedef // first overload: // - return all pareto-optimal solutions // - specify Label_Allocator and Visitor arguments -template void r_c_shortest_paths -( const Graph& g, - const VertexIndexMap& vertex_index_map, - const EdgeIndexMap& edge_index_map, - typename graph_traits::vertex_descriptor s, - typename graph_traits::vertex_descriptor t, +( const Graph& g, + const VertexIndexMap& vertex_index_map, + const EdgeIndexMap& edge_index_map, + typename graph_traits::vertex_descriptor s, + typename graph_traits::vertex_descriptor t, // each inner vector corresponds to a pareto-optimal path - std::vector::edge_descriptor> >& - pareto_optimal_solutions, - std::vector& pareto_optimal_resource_containers, - // to initialize the first label/resource container + std::vector::edge_descriptor> >& + pareto_optimal_solutions, + std::vector& 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, + 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, + Label_Allocator la, Visitor vis ) { - r_c_shortest_paths_dispatch( g, - vertex_index_map, - edge_index_map, - s, - t, - pareto_optimal_solutions, - pareto_optimal_resource_containers, - true, - rc, - ref, - dominance, - la, + r_c_shortest_paths_dispatch( g, + vertex_index_map, + edge_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 void r_c_shortest_paths -( const Graph& g, - const VertexIndexMap& vertex_index_map, - const EdgeIndexMap& edge_index_map, - typename graph_traits::vertex_descriptor s, - typename graph_traits::vertex_descriptor t, - std::vector::edge_descriptor>& - pareto_optimal_solution, - Resource_Container& pareto_optimal_resource_container, - // to initialize the first label/resource container +( const Graph& g, + const VertexIndexMap& vertex_index_map, + const EdgeIndexMap& edge_index_map, + typename graph_traits::vertex_descriptor s, + typename graph_traits::vertex_descriptor t, + std::vector::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, + 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, + Label_Allocator la, Visitor vis ) { // each inner vector corresponds to a pareto-optimal path - std::vector::edge_descriptor> > + std::vector::edge_descriptor> > pareto_optimal_solutions; std::vector pareto_optimal_resource_containers; - r_c_shortest_paths_dispatch( g, - vertex_index_map, - edge_index_map, - s, - t, - pareto_optimal_solutions, - pareto_optimal_resource_containers, - false, - rc, - ref, - dominance, - la, + r_c_shortest_paths_dispatch( g, + vertex_index_map, + edge_index_map, + s, + t, + pareto_optimal_solutions, + pareto_optimal_resource_containers, + false, + rc, + ref, + dominance, + la, vis ); if (!pareto_optimal_solutions.empty()) { pareto_optimal_solution = pareto_optimal_solutions[0]; @@ -618,83 +577,83 @@ void r_c_shortest_paths // third overload: // - return all pareto-optimal solutions // - use default Label_Allocator and Visitor -template void r_c_shortest_paths -( const Graph& g, - const VertexIndexMap& vertex_index_map, - const EdgeIndexMap& edge_index_map, - typename graph_traits::vertex_descriptor s, - typename graph_traits::vertex_descriptor t, +( const Graph& g, + const VertexIndexMap& vertex_index_map, + const EdgeIndexMap& edge_index_map, + typename graph_traits::vertex_descriptor s, + typename graph_traits::vertex_descriptor t, // each inner vector corresponds to a pareto-optimal path - std::vector::edge_descriptor> >& - pareto_optimal_solutions, - std::vector& pareto_optimal_resource_containers, - // to initialize the first label/resource container + std::vector::edge_descriptor> >& + pareto_optimal_solutions, + std::vector& 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 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, - pareto_optimal_solutions, - pareto_optimal_resource_containers, - true, - rc, - ref, - dominance, - default_r_c_shortest_paths_allocator(), + r_c_shortest_paths_dispatch( g, + vertex_index_map, + edge_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 void r_c_shortest_paths -( const Graph& g, - const VertexIndexMap& vertex_index_map, - const EdgeIndexMap& edge_index_map, - typename graph_traits::vertex_descriptor s, - typename graph_traits::vertex_descriptor t, - std::vector::edge_descriptor>& - pareto_optimal_solution, - Resource_Container& pareto_optimal_resource_container, - // to initialize the first label/resource container +( const Graph& g, + const VertexIndexMap& vertex_index_map, + const EdgeIndexMap& edge_index_map, + typename graph_traits::vertex_descriptor s, + typename graph_traits::vertex_descriptor t, + std::vector::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 Resource_Container& rc, + const Resource_Extension_Function& ref, const Dominance_Function& dominance ) { // each inner vector corresponds to a pareto-optimal path - std::vector::edge_descriptor> > + std::vector::edge_descriptor> > pareto_optimal_solutions; std::vector pareto_optimal_resource_containers; - r_c_shortest_paths_dispatch( g, - vertex_index_map, - edge_index_map, - s, - t, - pareto_optimal_solutions, - pareto_optimal_resource_containers, - false, - rc, - ref, - dominance, - default_r_c_shortest_paths_allocator(), + r_c_shortest_paths_dispatch( g, + vertex_index_map, + edge_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() ); if (!pareto_optimal_solutions.empty()) { pareto_optimal_solution = pareto_optimal_solutions[0]; @@ -705,26 +664,26 @@ void r_c_shortest_paths // check_r_c_path function -template -void check_r_c_path( const Graph& g, +void check_r_c_path( const Graph& g, const std::vector ::edge_descriptor>& ed_vec_path, - const Resource_Container& initial_resource_levels, - // if true, computed accumulated final resource levels must + ::edge_descriptor>& ed_vec_path, + const Resource_Container& initial_resource_levels, + // if true, computed accumulated final resource levels must // be equal to desired_final_resource_levels - // if false, computed accumulated final resource levels must + // if false, computed accumulated final resource levels must // be less than or equal to desired_final_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::edge_descriptor& + 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::edge_descriptor& ed_last_extended_arc ) { size_t i_size_ed_vec_path = ed_vec_path.size(); @@ -733,7 +692,7 @@ void check_r_c_path( const Graph& g, b_feasible = true; else { - if( i_size_ed_vec_path == 1 + if( i_size_ed_vec_path == 1 || target( ed_vec_path[0], g ) == source( ed_vec_path[1], g ) ) buf_path = ed_vec_path; else @@ -758,21 +717,21 @@ void check_r_c_path( const Graph& g, for( size_t i = 0; i < i_size_ed_vec_path; ++i ) { ed_last_extended_arc = buf_path[i]; - b_feasible = ref( g, - actual_final_resource_levels, - current_resource_levels, + b_feasible = ref( g, + actual_final_resource_levels, + current_resource_levels, buf_path[i] ); current_resource_levels = actual_final_resource_levels; if( !b_feasible ) return; } if( b_result_must_be_equal_to_desired_final_resource_levels ) - b_correctly_extended = - actual_final_resource_levels == desired_final_resource_levels ? + b_correctly_extended = + actual_final_resource_levels == desired_final_resource_levels ? true : false; else { - if( actual_final_resource_levels < desired_final_resource_levels + if( actual_final_resource_levels < desired_final_resource_levels || actual_final_resource_levels == desired_final_resource_levels ) b_correctly_extended = true; } diff --git a/include/boost/graph/subgraph.hpp b/include/boost/graph/subgraph.hpp index 22706bc61..0afb2cabb 100644 --- a/include/boost/graph/subgraph.hpp +++ b/include/boost/graph/subgraph.hpp @@ -371,46 +371,56 @@ typename subgraph::vertex_descriptor add_vertex(typename subgraph::vertex_descriptor u_global, subgraph& g) { - BOOST_ASSERT(!g.is_root()); - typename subgraph::vertex_descriptor u_local, v_global; - typename subgraph::edge_descriptor e_global; - - u_local = add_vertex(g.m_graph); - g.m_global_vertex.push_back(u_global); - g.m_local_vertex[u_global] = u_local; - - subgraph& r = g.root(); + if (g.is_root()) { + return u_global; + } else { + typename subgraph::vertex_descriptor u_local; + bool exists_local; + boost::tie(u_local, exists_local) = g.find_vertex(u_global); + + if (!exists_local) { + typename subgraph::vertex_descriptor v_global; + typename subgraph::edge_descriptor e_global; + // call recursion for parent subgraph + add_vertex(u_global, g.parent()); + + u_local = add_vertex(g.m_graph); + g.m_global_vertex.push_back(u_global); + g.m_local_vertex[u_global] = u_local; + + subgraph& r = g.root(); - // remember edge global and local maps - { - typename subgraph::out_edge_iterator ei, ei_end; - for (boost::tie(ei, ei_end) = out_edges(u_global, r); - ei != ei_end; ++ei) { - e_global = *ei; - v_global = target(e_global, r); - if (g.find_vertex(v_global).second == true) - g.local_add_edge(u_local, g.global_to_local(v_global), e_global); - } - } - if (is_directed(g)) { // not necessary for undirected graph - typename subgraph::vertex_iterator vi, vi_end; - typename subgraph::out_edge_iterator ei, ei_end; - for(boost::tie(vi, vi_end) = vertices(r); vi != vi_end; ++vi) { - v_global = *vi; - if (v_global == u_global) - continue; // don't insert self loops twice! - if (!g.find_vertex(v_global).second) - continue; // not a subgraph vertex => try next one - for(boost::tie(ei, ei_end) = out_edges(*vi, r); ei != ei_end; ++ei) { - e_global = *ei; - if(target(e_global, r) == u_global) { - g.local_add_edge(g.global_to_local(v_global), u_local, e_global); + // remember edge global and local maps + { + typename subgraph::out_edge_iterator ei, ei_end; + for (boost::tie(ei, ei_end) = out_edges(u_global, r); + ei != ei_end; ++ei) { + e_global = *ei; + v_global = target(e_global, r); + if (g.find_vertex(v_global).second == true) + g.local_add_edge(u_local, g.global_to_local(v_global), e_global); + } + } + if (is_directed(g)) { // not necessary for undirected graph + typename subgraph::vertex_iterator vi, vi_end; + typename subgraph::out_edge_iterator ei, ei_end; + for(boost::tie(vi, vi_end) = vertices(r); vi != vi_end; ++vi) { + v_global = *vi; + if (v_global == u_global) + continue; // don't insert self loops twice! + if (!g.find_vertex(v_global).second) + continue; // not a subgraph vertex => try next one + for(boost::tie(ei, ei_end) = out_edges(*vi, r); ei != ei_end; ++ei) { + e_global = *ei; + if(target(e_global, r) == u_global) { + g.local_add_edge(g.global_to_local(v_global), u_local, e_global); + } + } } } } + return u_local; } - - return u_local; } // NOTE: Descriptors are local unless otherwise noted. diff --git a/include/boost/graph/successive_shortest_path_nonnegative_weights.hpp b/include/boost/graph/successive_shortest_path_nonnegative_weights.hpp index 72b1512c1..6a3aeb168 100644 --- a/include/boost/graph/successive_shortest_path_nonnegative_weights.hpp +++ b/include/boost/graph/successive_shortest_path_nonnegative_weights.hpp @@ -1,6 +1,6 @@ //======================================================================= // Copyright 2013 University of Warsaw. -// Authors: Piotr Wygocki +// Authors: Piotr Wygocki // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -11,7 +11,7 @@ // by Ahuja, Magnanti, Orlin. #ifndef BOOST_GRAPH_SUCCESSIVE_SHORTEST_PATH_HPP -#define BOOST_GRAPH_SUCCESSIVE_SHORTEST_PATH_HPP +#define BOOST_GRAPH_SUCCESSIVE_SHORTEST_PATH_HPP #include @@ -19,7 +19,6 @@ #include #include #include -#include #include #include #include @@ -29,9 +28,9 @@ namespace boost { namespace detail { - + template -class MapReducedWeight : +class MapReducedWeight : public put_get_helper::value_type, MapReducedWeight > { typedef graph_traits gtraits; public: @@ -39,11 +38,11 @@ class MapReducedWeight : typedef typename property_traits::value_type value_type; typedef value_type reference; typedef typename gtraits::edge_descriptor key_type; - MapReducedWeight(const Graph & g, Weight w, Distance d, Reversed r) : + MapReducedWeight(const Graph & g, Weight w, Distance d, Reversed r) : g_(g), weight_(w), distance_(d), rev_(r) {} reference operator[](key_type v) const { - return get(distance_, source(v, g_)) - get(distance_,target(v, g_)) + get(weight_, v); + return get(distance_, source(v, g_)) - get(distance_,target(v, g_)) + get(weight_, v); } private: const Graph & g_; @@ -53,7 +52,7 @@ class MapReducedWeight : }; template -MapReducedWeight +MapReducedWeight make_mapReducedWeight(const Graph & g, Weight w, Distance d, Reversed r) { return MapReducedWeight(g, w, d, r); } @@ -63,21 +62,21 @@ make_mapReducedWeight(const Graph & g, Weight w, Distance d, Reversed r) { template void successive_shortest_path_nonnegative_weights( - const Graph &g, - typename graph_traits::vertex_descriptor s, + const Graph &g, + typename graph_traits::vertex_descriptor s, typename graph_traits::vertex_descriptor t, Capacity capacity, ResidualCapacity residual_capacity, - Weight weight, + Weight weight, Reversed rev, VertexIndex index, - Pred pred, + Pred pred, Distance distance, Distance2 distance_prev) { filtered_graph > gres = detail::residual_graph(g, residual_capacity); typedef typename graph_traits::edge_descriptor edge_descriptor; - + BGL_FORALL_EDGES_T(e, g, Graph) { put(residual_capacity, e, get(capacity, e)); } @@ -90,7 +89,7 @@ void successive_shortest_path_nonnegative_weights( BGL_FORALL_VERTICES_T(v, g, Graph) { put(pred, v, edge_descriptor()); } - dijkstra_shortest_paths(gres, s, + dijkstra_shortest_paths(gres, s, weight_map(detail::make_mapReducedWeight(gres, weight, distance_prev, rev)). distance_map(distance). vertex_index_map(index). @@ -113,8 +112,8 @@ namespace detail { template void successive_shortest_path_nonnegative_weights_dispatch3( - const Graph &g, - typename graph_traits::vertex_descriptor s, + const Graph &g, + typename graph_traits::vertex_descriptor s, typename graph_traits::vertex_descriptor t, Capacity capacity, ResidualCapacity residual_capacity, @@ -130,8 +129,8 @@ void successive_shortest_path_nonnegative_weights_dispatch3( //setting default distance map template void successive_shortest_path_nonnegative_weights_dispatch3( - Graph &g, - typename graph_traits::vertex_descriptor s, + Graph &g, + typename graph_traits::vertex_descriptor s, typename graph_traits::vertex_descriptor t, Capacity capacity, ResidualCapacity residual_capacity, @@ -151,8 +150,8 @@ void successive_shortest_path_nonnegative_weights_dispatch3( template void successive_shortest_path_nonnegative_weights_dispatch2( - Graph &g, - typename graph_traits::vertex_descriptor s, + Graph &g, + typename graph_traits::vertex_descriptor s, typename graph_traits::vertex_descriptor t, Capacity capacity, ResidualCapacity residual_capacity, @@ -168,8 +167,8 @@ void successive_shortest_path_nonnegative_weights_dispatch2( //setting default distance map template void successive_shortest_path_nonnegative_weights_dispatch2( - Graph &g, - typename graph_traits::vertex_descriptor s, + Graph &g, + typename graph_traits::vertex_descriptor s, typename graph_traits::vertex_descriptor t, Capacity capacity, ResidualCapacity residual_capacity, @@ -177,7 +176,7 @@ void successive_shortest_path_nonnegative_weights_dispatch2( Reversed rev, VertexIndex index, Pred pred, - param_not_found, + param_not_found, const bgl_named_params& params) { typedef typename property_traits::value_type D; @@ -190,12 +189,12 @@ void successive_shortest_path_nonnegative_weights_dispatch2( template void successive_shortest_path_nonnegative_weights_dispatch1( - Graph &g, - typename graph_traits::vertex_descriptor s, + Graph &g, + typename graph_traits::vertex_descriptor s, typename graph_traits::vertex_descriptor t, Capacity capacity, ResidualCapacity residual_capacity, - Weight weight, + Weight weight, Reversed rev, VertexIndex index, Pred pred, @@ -207,12 +206,12 @@ void successive_shortest_path_nonnegative_weights_dispatch1( //setting default predecessors map template void successive_shortest_path_nonnegative_weights_dispatch1( - Graph &g, - typename graph_traits::vertex_descriptor s, + Graph &g, + typename graph_traits::vertex_descriptor s, typename graph_traits::vertex_descriptor t, Capacity capacity, ResidualCapacity residual_capacity, - Weight weight, + Weight weight, Reversed rev, VertexIndex index, param_not_found, @@ -220,9 +219,9 @@ void successive_shortest_path_nonnegative_weights_dispatch1( typedef typename graph_traits::edge_descriptor edge_descriptor; std::vector pred_vec(num_vertices(g)); - successive_shortest_path_nonnegative_weights_dispatch2(g, s, t, capacity, residual_capacity, weight, rev, index, + successive_shortest_path_nonnegative_weights_dispatch2(g, s, t, capacity, residual_capacity, weight, rev, index, make_iterator_property_map(pred_vec.begin(), index), - get_param(params, vertex_distance), params); + get_param(params, vertex_distance), params); } }//detail @@ -230,26 +229,26 @@ void successive_shortest_path_nonnegative_weights_dispatch1( template void successive_shortest_path_nonnegative_weights( - Graph &g, - typename graph_traits::vertex_descriptor s, + Graph &g, + typename graph_traits::vertex_descriptor s, typename graph_traits::vertex_descriptor t, const bgl_named_params& params) { - - return detail::successive_shortest_path_nonnegative_weights_dispatch1(g, s, t, + + return detail::successive_shortest_path_nonnegative_weights_dispatch1(g, s, t, choose_const_pmap(get_param(params, edge_capacity), g, edge_capacity), - choose_pmap(get_param(params, edge_residual_capacity), + choose_pmap(get_param(params, edge_residual_capacity), g, edge_residual_capacity), choose_const_pmap(get_param(params, edge_weight), g, edge_weight), choose_const_pmap(get_param(params, edge_reverse), g, edge_reverse), choose_const_pmap(get_param(params, vertex_index), g, vertex_index), - get_param(params, vertex_predecessor), + get_param(params, vertex_predecessor), params); } template void successive_shortest_path_nonnegative_weights( Graph &g, - typename graph_traits::vertex_descriptor s, + typename graph_traits::vertex_descriptor s, typename graph_traits::vertex_descriptor t) { bgl_named_params params(0); successive_shortest_path_nonnegative_weights(g, s, t, params); @@ -258,4 +257,3 @@ void successive_shortest_path_nonnegative_weights( }//boost #endif /* BOOST_GRAPH_SUCCESSIVE_SHORTEST_PATH_HPP */ - diff --git a/include/boost/pending/relaxed_heap.hpp b/include/boost/pending/relaxed_heap.hpp index 42da49e7d..f7523eb1b 100644 --- a/include/boost/pending/relaxed_heap.hpp +++ b/include/boost/pending/relaxed_heap.hpp @@ -6,6 +6,7 @@ // Authors: Douglas Gregor // Andrew Lumsdaine +#warning "Use of relaxed_heap is depreciated; please use the standard heap functions." #ifndef BOOST_RELAXED_HEAP_HEADER #define BOOST_RELAXED_HEAP_HEADER diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 5e5871fe2..82779402d 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -77,6 +77,7 @@ test-suite graph_test : # TODO: Merge these into a single test framework. [ run subgraph.cpp ../../test/build//boost_test_exec_monitor ] [ run subgraph_bundled.cpp ] + [ run subgraph_add.cpp ../../test/build//boost_unit_test_framework/static : $(TEST_DIR) ] [ run subgraph_props.cpp ] [ run isomorphism.cpp ../../test/build//boost_test_exec_monitor ] @@ -140,6 +141,7 @@ test-suite graph_test : [ run strong_components_test.cpp ] [ run find_flow_cost_bundled_properties_and_named_params_test.cpp ../../test/build//boost_unit_test_framework/static ] [ run max_flow_algorithms_bundled_properties_and_named_params.cpp ../../test/build//boost_unit_test_framework/static ] + [ run delete_edge.cpp ] ; # Run SDB tests only when -sSDB= is set. diff --git a/test/delete_edge.cpp b/test/delete_edge.cpp new file mode 100644 index 000000000..ebc11228c --- /dev/null +++ b/test/delete_edge.cpp @@ -0,0 +1,58 @@ +//======================================================================= +// Copyright 2018 +// Authors: Rasmus Ahlberg +// +// 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 + +#include + +int test_main(int argc, char* argv[]) +{ + typedef int Vertex; + typedef int Edge; + + typedef boost::adjacency_list Graph_t; + + typedef Graph_t::edge_descriptor EdgeDesc; + typedef Graph_t::vertex_descriptor VertexType; + + Graph_t m_graph; + + VertexType v1 = boost::add_vertex(m_graph); + VertexType v2 = boost::add_vertex(m_graph); + VertexType v3 = boost::add_vertex(m_graph); + + EdgeDesc ed1; + bool inserted1; + + boost::tie(ed1, inserted1) = boost::add_edge(v3, v1, m_graph); + + BOOST_REQUIRE(inserted1); + + static const int EDGE_VAL = 1234; + + m_graph[ed1] = EDGE_VAL; + + boost::remove_vertex(v2, m_graph); + + std::cout << "ed1 " << m_graph[ed1] << std::endl; + + BOOST_REQUIRE(m_graph[ed1] == EDGE_VAL); + + return 0; +} diff --git a/test/dijkstra_heap_performance.cpp b/test/dijkstra_heap_performance.cpp index 2cab3fbf2..8e290224b 100644 --- a/test/dijkstra_heap_performance.cpp +++ b/test/dijkstra_heap_performance.cpp @@ -50,7 +50,7 @@ struct show_events_visitor : dijkstra_visitor<> template -void run_test(const Graph& g, const char* name, Kind kind, +void run_test(const Graph& g, const char* name, Kind kind, const std::vector& correct_distances) { std::vector distances(num_vertices(g)); @@ -111,11 +111,7 @@ int main(int argc, char* argv[]) std::cout << "Running Dijkstra's with binary heap..."; std::cout.flush(); timer t; -#ifdef BOOST_GRAPH_DIJKSTRA_TESTING_DIETMAR - dijkstra_heap_kind = dijkstra_binary_heap; -#else - dijkstra_relaxed_heap = false; -#endif + dijkstra_shortest_paths(g, vertex(0, g), distance_map( boost::make_iterator_property_map( @@ -123,19 +119,11 @@ int main(int argc, char* argv[]) double binary_heap_time = t.elapsed(); std::cout << binary_heap_time << " seconds.\n"; - // Run relaxed heap version -#ifdef BOOST_GRAPH_DIJKSTRA_USE_RELAXED_HEAP - std::cout << "Running Dijkstra's with relaxed heap..."; -#else + std::cout << "Running Dijkstra's with d-ary heap (d=4)..."; -#endif std::cout.flush(); t.restart(); -#ifdef BOOST_GRAPH_DIJKSTRA_TESTING_DIETMAR - dijkstra_heap_kind = dijkstra_relaxed_heap; -#else - dijkstra_relaxed_heap = true; -#endif + dijkstra_shortest_paths(g, vertex(0, g), distance_map( boost::make_iterator_property_map( @@ -148,18 +136,11 @@ int main(int argc, char* argv[]) BOOST_TEST(binary_heap_distances == relaxed_heap_distances); // Run Michael's no-color-map version -#ifdef BOOST_GRAPH_DIJKSTRA_USE_RELAXED_HEAP - std::cout << "Running Dijkstra's (no color map) with relaxed heap..."; -#else + std::cout << "Running Dijkstra's (no color map) with d-ary heap (d=4)..."; -#endif std::cout.flush(); t.restart(); -#ifdef BOOST_GRAPH_DIJKSTRA_TESTING_DIETMAR - dijkstra_heap_kind = dijkstra_relaxed_heap; -#else - dijkstra_relaxed_heap = true; -#endif + dijkstra_shortest_paths_no_color_map (g, vertex(0, g), boost::dummy_property_map(), diff --git a/test/r_c_shortest_paths_test.cpp b/test/r_c_shortest_paths_test.cpp index cf6d57e16..246271780 100644 --- a/test/r_c_shortest_paths_test.cpp +++ b/test/r_c_shortest_paths_test.cpp @@ -1,6 +1,6 @@ // Copyright Michael Drexl 2005, 2006. // Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at +// (See accompanying file LICENSE_1_0.txt or copy at // http://boost.org/LICENSE_1_0.txt) #include @@ -20,7 +20,7 @@ using namespace boost; struct SPPRC_Example_Graph_Vert_Prop { - SPPRC_Example_Graph_Vert_Prop( int n = 0, int e = 0, int l = 0 ) + 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 @@ -31,7 +31,7 @@ struct SPPRC_Example_Graph_Vert_Prop struct SPPRC_Example_Graph_Arc_Prop { - SPPRC_Example_Graph_Arc_Prop( int n = 0, int c = 0, int t = 0 ) + SPPRC_Example_Graph_Arc_Prop( int n = 0, int c = 0, int t = 0 ) : num( n ), cost( c ), time( t ) {} int num; // traversal cost @@ -40,11 +40,11 @@ struct SPPRC_Example_Graph_Arc_Prop int time; }; -typedef adjacency_list +typedef adjacency_list SPPRC_Example_Graph; // data structures for spp without resource constraints: @@ -63,13 +63,13 @@ struct spp_no_rc_res_cont int cost; }; -bool operator==( const spp_no_rc_res_cont& res_cont_1, +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, +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 ); @@ -79,9 +79,9 @@ bool operator<( const spp_no_rc_res_cont& res_cont_1, 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, + 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 ::edge_descriptor ed ) const { @@ -94,7 +94,7 @@ class ref_no_res_cont class dominance_no_res_cont { public: - inline bool operator()( const spp_no_rc_res_cont& res_cont_1, + 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!!! @@ -102,15 +102,15 @@ class dominance_no_res_cont 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 + // "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 + // 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 } }; @@ -133,14 +133,14 @@ struct spp_spptw_res_cont int time; }; -bool operator==( const spp_spptw_res_cont& res_cont_1, +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 + 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, +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 ) @@ -154,15 +154,15 @@ bool operator<( const spp_spptw_res_cont& res_cont_1, 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, + inline bool operator()( const SPPRC_Example_Graph& g, + spp_spptw_res_cont& new_cont, + const spp_spptw_res_cont& old_cont, graph_traits ::edge_descriptor ed ) const { - const SPPRC_Example_Graph_Arc_Prop& arc_prop = + const SPPRC_Example_Graph_Arc_Prop& arc_prop = get( edge_bundle, g )[ed]; - const SPPRC_Example_Graph_Vert_Prop& vert_prop = + 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; @@ -176,29 +176,112 @@ class ref_spptw class dominance_spptw { public: - inline bool operator()( const spp_spptw_res_cont& res_cont_1, + 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 + 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 + // "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 + // 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 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 + ::edge_descriptor ed) const { + const graph_traits ::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 test_main(int, char*[]) { SPPRC_Example_Graph g; @@ -262,12 +345,12 @@ int test_main(int, char*[]) 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 ::edge_descriptor> > + ::edge_descriptor> > opt_solutions; std::vector pareto_opt_rcs_no_rc; std::vector i_vec_opt_solutions_spp_no_rc; @@ -277,19 +360,19 @@ int test_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, - pareto_opt_rcs_no_rc, - spp_no_rc_res_cont( 0 ), - ref_no_res_cont(), - dominance_no_res_cont(), + ( 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 >(), + >(), 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 << ": "; @@ -297,23 +380,23 @@ int test_main(int, char*[]) } } - //std::vector::vertex_descriptor> + //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, + // 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 ) // { @@ -430,14 +513,14 @@ int test_main(int, char*[]) // spptw std::vector ::edge_descriptor> > + ::edge_descriptor> > opt_solutions_spptw; std::vector pareto_opt_rcs_spptw; std::vector ::edge_descriptor> > > > + ::edge_descriptor> > > > vec_vec_vec_vec_opt_solutions_spptw( 10 ); for( int s = 0; s < 10; ++s ) @@ -445,56 +528,56 @@ int test_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_spptw, - pareto_opt_rcs_spptw, + ( 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(), + spp_spptw_res_cont( 0, g[s].eat ), + ref_spptw(), + dominance_spptw(), std::allocator >(), + >(), 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_feasible = false; bool b_correctly_extended = false; spp_spptw_res_cont actual_final_resource_levels( 0, 0 ); graph_traits::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, + 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_CHECK(b_is_a_path_at_all && b_feasible && b_correctly_extended); b_is_a_path_at_all = false; - b_feasible = false; + b_feasible = false; b_correctly_extended = false; spp_spptw_res_cont actual_final_resource_levels2( 0, 0 ); graph_traits::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, + 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_CHECK(b_is_a_path_at_all && b_feasible && b_correctly_extended); } @@ -605,7 +688,7 @@ int test_main(int, char*[]) for( int s = 0; s < 10; ++s ) for( int t = 0; t < 10; ++t ) BOOST_CHECK( static_cast - ( vec_vec_vec_vec_opt_solutions_spptw[s][t].size() ) == + ( vec_vec_vec_vec_opt_solutions_spptw[s][t].size() ) == i_vec_correct_num_solutions_spptw[10 * s + t] ); // one pareto-optimal solution @@ -620,22 +703,97 @@ int test_main(int, char*[]) add_edge( 2, 3, SPPRC_Example_Graph_Arc_Prop( 3, 1, 1 ), g2 ); std::vector::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(), + 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 >(), + >(), default_r_c_shortest_paths_visitor() ); BOOST_CHECK(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::edge_descriptor> > + pareto_opt_marked_solutions; + std::vector pareto_opt_marked_resource_containers; + + graph_traits::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 + >(), + default_r_c_shortest_paths_visitor() ); + + BOOST_CHECK(!pareto_opt_marked_solutions.empty()); + std::vector::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::edge_descriptor> &path = *path_it; + BOOST_CHECK(!path.empty()); + + const graph_traits::edge_descriptor front = path.front(); + BOOST_CHECK(boost::target(front, g3) == g3_target); + + std::vector::edge_descriptor>::const_iterator edge_it, edge_it_end; + graph_traits::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::edge_descriptor edge = *edge_it; + + graph_traits::vertex_descriptor prev_end, current_end; + prev_end = boost::source(prev_edge, g3); + current_end = boost::target(edge, g3); + BOOST_CHECK(prev_end == current_end); + + prev_edge = edge; + } + + const graph_traits::edge_descriptor back = path.back(); + BOOST_CHECK(boost::source(back, g3) == g3_source); + } + return 0; } diff --git a/test/relaxed_heap_test.cpp b/test/relaxed_heap_test.cpp deleted file mode 100644 index 3bad264a7..000000000 --- a/test/relaxed_heap_test.cpp +++ /dev/null @@ -1,265 +0,0 @@ -// Copyright 2004 The Trustees of Indiana University. - -// Use, modification and distribution is subject to 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) - -// Authors: Douglas Gregor -// Andrew Lumsdaine -#ifndef BOOST_RELAXED_HEAP_DEBUG -# define BOOST_RELAXED_HEAP_DEBUG 0 -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -typedef std::vector > values_type; -values_type values; - -struct less_extvalue -{ - typedef bool result_type; - - bool operator()(unsigned x, unsigned y) const - { - assert(values[x] && values[y]); - return values[x] < values[y]; - } -}; - -using namespace std; - -boost::optional get_min_value() -{ - boost::optional min_value; - for (unsigned i = 0; i < values.size(); ++i) { - if (values[i]) { - if (!min_value || *values[i] < *min_value) min_value = values[i]; - } - } - return min_value; -} - -void interactive_test() -{ - unsigned max_values; - cout << "Enter max number of values in the heap> "; - cin >> max_values; - - values.resize(max_values); - boost::relaxed_heap heap(max_values); - - char option; - do { - cout << "Enter command> "; - if (cin >> option) { - switch (option) { - case 'i': case 'I': - { - unsigned index; - double value; - if (cin >> index >> value) { - if (index >= values.size()) cout << "Index out of range.\n"; - else if (values[index]) cout << "Already in queue.\n"; - else { - values[index] = value; - heap.push(index); - heap.dump_tree(); - } - } - } - break; - - case 'u': case 'U': - { - unsigned index; - double value; - if (cin >> index >> value) { - if (index >= values.size()) cout << "Index out of range.\n"; - else if (!values[index]) cout << "Not in queue.\n"; - else { - values[index] = value; - heap.update(index); - heap.dump_tree(); - } - } - } - break; - - case 'r': case 'R': - { - unsigned index; - if (cin >> index) { - if (index >= values.size()) cout << "Index out of range.\n"; - else if (!values[index]) cout << "Not in queue.\n"; - else { - heap.remove(index); - heap.dump_tree(); - } - } - } - break; - - case 't': case 'T': - { - if (boost::optional min_value = get_min_value()) { - cout << "Top value is (" << heap.top() << ", " - << *values[heap.top()] << ").\n"; - BOOST_CHECK(*min_value == *values[heap.top()]); - } else { - cout << "Queue is empty.\n"; - BOOST_CHECK(heap.empty()); - } - } - break; - - case 'd': case 'D': - { - if (boost::optional min_value = get_min_value()) { - unsigned victim = heap.top(); - double value = *values[victim]; - cout << "Removed top value (" << victim << ", " << value << ")\n"; - BOOST_CHECK(*min_value == value); - - heap.pop(); - heap.dump_tree(); - values[victim].reset(); - } else { - cout << "Queue is empty.\n"; - BOOST_CHECK(heap.empty()); - } - } - break; - - case 'q': case 'Q': - break; - - default: - cout << "Unknown command '" << option << "'.\n"; - } - } - } while (cin && option != 'q' && option != 'Q'); -} - -void random_test(int n, int iterations, int seed) -{ - values.resize(n); - boost::relaxed_heap heap(n); - boost::minstd_rand gen(seed); - boost::uniform_int rand_index(0, n-1); - boost::uniform_real<> rand_value(-1000.0, 1000.0); - boost::uniform_int which_option(0, 3); - - cout << n << std::endl; - -#if BOOST_RELAXED_HEAP_DEBUG > 1 - heap.dump_tree(); -#endif - - BOOST_REQUIRE(heap.valid()); - -#if BOOST_RELAXED_HEAP_DEBUG == 0 - boost::progress_display progress(iterations); -#endif - - for (int iteration = 0; iteration < iterations; ++iteration) { -#if BOOST_RELAXED_HEAP_DEBUG > 1 - std::cout << "Iteration #" << iteration << std::endl; -#endif - unsigned victim = rand_index(gen); - if (values[victim]) { - switch (which_option(gen)) { - case 0: case 3: - { - // Update with a smaller weight - boost::uniform_real<> rand_smaller((rand_value.min)(), *values[victim]); - values[victim] = rand_smaller(gen); - assert(*values[victim] >= (rand_smaller.min)()); - assert(*values[victim] <= (rand_smaller.max)()); - -#if BOOST_RELAXED_HEAP_DEBUG > 0 - cout << "u " << victim << " " << *values[victim] << std::endl; - cout.flush(); -#endif - heap.update(victim); - } - break; - - case 1: - { - // Delete minimum value in the queue. - victim = heap.top(); - double top_value = *values[victim]; - BOOST_CHECK(*get_min_value() == top_value); - if (*get_min_value() != top_value) return; -#if BOOST_RELAXED_HEAP_DEBUG > 0 - cout << "d" << std::endl; - cout.flush(); -#endif - heap.pop(); - values[victim].reset(); -#if BOOST_RELAXED_HEAP_DEBUG > 1 - cout << "(Removed " << victim << ")\n"; -#endif // BOOST_RELAXED_HEAP_DEBUG > 1 - } - break; - - case 2: - { - // Just remove this value from the queue completely - values[victim].reset(); -#if BOOST_RELAXED_HEAP_DEBUG > 0 - cout << "r " << victim << std::endl; - cout.flush(); -#endif - heap.remove(victim); - } - break; - - default: - cout << "Random number generator failed." << endl; - BOOST_CHECK(false); - return; - break; - } - } else { - values[victim] = rand_value(gen); - assert(*values[victim] >= (rand_value.min)()); - assert(*values[victim] <= (rand_value.max)()); - -#if BOOST_RELAXED_HEAP_DEBUG > 0 - cout << "i " << victim << " " << *values[victim] << std::endl; - cout.flush(); -#endif - heap.push(victim); - } - -#if BOOST_RELAXED_HEAP_DEBUG > 1 - heap.dump_tree(); -#endif // BOOST_RELAXED_HEAP_DEBUG > 1 - - BOOST_REQUIRE(heap.valid()); - -#if BOOST_RELAXED_HEAP_DEBUG == 0 - ++progress; -#endif - } -} - -int test_main(int argc, char* argv[]) -{ - if (argc >= 3) { - int n = boost::lexical_cast(argv[1]); - int iterations = boost::lexical_cast(argv[2]); - int seed = (argc >= 4? boost::lexical_cast(argv[3]) : 1); - random_test(n, iterations, seed); - } else interactive_test(); - return 0; -} diff --git a/test/subgraph_add.cpp b/test/subgraph_add.cpp new file mode 100644 index 000000000..a6a3d3644 --- /dev/null +++ b/test/subgraph_add.cpp @@ -0,0 +1,275 @@ +/* This file is a boost.test unit test and provides tests the internal dependency graph + * + * Created on: 06.10.2015 + * Author: Stefan Hammer + * License: Boost Software License, Version 1.0. (See + * accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * + */ + +#define BOOST_TEST_MODULE subgraph_add + +// std lib includes +#include + +// include boost components +#include +#include +#include + +// include header +#include + +using namespace boost; + +BOOST_AUTO_TEST_CASE(simpleGraph) { + + BOOST_TEST_MESSAGE("simple subgraph"); + + typedef subgraph< adjacency_list< vecS, vecS, directedS, + no_property, property< edge_index_t, int > > > Graph; + + const int N = 6; + Graph G0(N); + + enum { A, B, C, D, E, F}; // for conveniently refering to vertices in G0 + + Graph& G1 = G0.create_subgraph(); + Graph& G2 = G1.create_subgraph(); + + BOOST_CHECK(&G1.parent() == &G0); + BOOST_CHECK(&G2.parent() == &G1); + + enum { A1, B1, C1 }; // for conveniently refering to vertices in G1 + enum { A2, B2, C2 }; // for conveniently refering to vertices in G2 + + add_vertex(C, G1); // global vertex C becomes local A1 for G1 + add_vertex(E, G1); // global vertex E becomes local B1 for G1 + add_vertex(F, G1); // global vertex F becomes local C1 for G1 + + add_vertex(C, G2); // global vertex C becomes local A2 for G2 + add_vertex(E, G2); // global vertex E becomes local B2 for G2 + + BOOST_CHECK(num_vertices(G0) == 6); + BOOST_CHECK(num_vertices(G1) == 3); + std::cerr << num_vertices(G1) << std::endl; + BOOST_CHECK(num_vertices(G2) == 2); + + // add edges to root graph + add_edge(A, B, G0); + add_edge(B, C, G0); + add_edge(B, D, G0); + add_edge(E, F, G0); + + BOOST_CHECK(num_edges(G0) == 4); + BOOST_CHECK(num_edges(G1) == 1); + BOOST_CHECK(num_edges(G2) == 0); + + // add edges to G1 + add_edge(A1, B1, G1); + BOOST_CHECK(num_edges(G0) == 5); + BOOST_CHECK(num_edges(G1) == 2); + BOOST_CHECK(num_edges(G2) == 1); + // num_vertices stays the same + BOOST_CHECK(num_vertices(G0) == 6); + BOOST_CHECK(num_vertices(G1) == 3); + BOOST_CHECK(num_vertices(G2) == 2); +} + +BOOST_AUTO_TEST_CASE(addVertices) { + + BOOST_TEST_MESSAGE("subgraph add edges"); + + typedef subgraph< adjacency_list< vecS, vecS, directedS, + no_property, property< edge_index_t, int > > > Graph; + typedef Graph::vertex_descriptor Vertex; + + const int N = 3; + Graph G0(N); + Graph& G1 = G0.create_subgraph(); + Graph& G2 = G1.create_subgraph(); + + BOOST_CHECK(&G1.parent() == &G0); + BOOST_CHECK(&G2.parent() == &G1); + + // add vertices to G2 + Vertex n1 = add_vertex(0, G2); + Vertex n2 = add_vertex(1, G2); + // check if the global vertex 2 is equal to the returned local vertex + if (G2.find_vertex(0).second) { + BOOST_CHECK(G2.find_vertex(0).first == n1); + } else { + BOOST_ERROR( "vertex not found!" ); + } + if (G2.find_vertex(1).second) { + BOOST_CHECK(G2.find_vertex(1).first == n2); + } else { + BOOST_ERROR( "vertex not found!" ); + } + // and check if this vertex is also present in G1 + if (G1.find_vertex(0).second) { + BOOST_CHECK(G1.local_to_global(G1.find_vertex(0).first) == 0); + } else { + BOOST_ERROR( "vertex not found!" ); + } + if (G1.find_vertex(0).second) { + BOOST_CHECK(G1.local_to_global(G1.find_vertex(1).first) == 1); + } else { + BOOST_ERROR( "vertex not found!" ); + } + + // num_vertices stays the same + BOOST_CHECK(num_vertices(G0) == 3); + BOOST_CHECK(num_vertices(G1) == 2); + BOOST_CHECK(num_vertices(G2) == 2); + + // add vertices to G1 + Vertex n3 = add_vertex(2, G1); + // check if the global vertex 2 is equal to the returned local vertex + if (G1.find_vertex(2).second) { + BOOST_CHECK(G1.find_vertex(2).first == n3); + } else { + BOOST_ERROR( "vertex not found!" ); + } + // num_vertices stays the same + BOOST_CHECK(num_vertices(G0) == 3); + BOOST_CHECK(num_vertices(G1) == 3); + BOOST_CHECK(num_vertices(G2) == 2); + + // add vertices to G1 + Vertex n4 = add_vertex(G1); + + // check if the new local vertex is also in the global graph + BOOST_CHECK(G0.find_vertex(G1.local_to_global(n4)).second); + // check if the new local vertex is not in the subgraphs + BOOST_CHECK(!G2.find_vertex(n4).second); + + // num_vertices stays the same + BOOST_CHECK(num_vertices(G0) == 4); + BOOST_CHECK(num_vertices(G1) == 4); + BOOST_CHECK(num_vertices(G2) == 2); + + // add vertices to G0 + Vertex n5 = add_vertex(G0); + + // check if the new local vertex is not in the subgraphs + BOOST_CHECK(!G1.find_vertex(n5).second); + BOOST_CHECK(!G2.find_vertex(n5).second); + + // num_vertices stays the same + BOOST_CHECK(num_vertices(G0) == 5); + BOOST_CHECK(num_vertices(G1) == 4); + BOOST_CHECK(num_vertices(G2) == 2); + + typedef std::map::vertex_descriptor, graph_traits::vertex_descriptor>::iterator v_itr; + + std::cerr << "All G0 vertices: " << std::endl; + for(v_itr v = G0.m_local_vertex.begin(); v != G0.m_local_vertex.end(); ++v) { + std::cerr << G0.local_to_global(v->first) << std::endl; + } + std::cerr << "All G1 vertices: " << std::endl; + for(v_itr v = G1.m_local_vertex.begin(); v != G1.m_local_vertex.end(); ++v) { + std::cerr << G1.local_to_global(v->first) << std::endl; + } + std::cerr << "All G2 vertices: " << std::endl; + for(v_itr v = G2.m_local_vertex.begin(); v != G2.m_local_vertex.end(); ++v) { + std::cerr << G2.local_to_global(v->first) << std::endl; + } +} + +BOOST_AUTO_TEST_CASE(addEdge) { + + BOOST_TEST_MESSAGE("subgraph add edges"); + + typedef subgraph< adjacency_list< vecS, vecS, directedS, + no_property, property< edge_index_t, int > > > Graph; + typedef Graph::vertex_descriptor Vertex; + + const int N = 3; + Graph G0(N); + Graph& G1 = G0.create_subgraph(); + Graph& G2 = G1.create_subgraph(); + + BOOST_CHECK(&G1.parent() == &G0); + BOOST_CHECK(&G2.parent() == &G1); + + // add vertices + add_vertex(0, G2); + add_vertex(1, G2); + BOOST_CHECK(num_vertices(G1) == 2); + BOOST_CHECK(num_vertices(G2) == 2); + + // add edge to G0 which needs propagation + add_edge(0, 1, G0); + + BOOST_CHECK(num_edges(G0) == 1); + BOOST_CHECK(num_edges(G1) == 1); + BOOST_CHECK(num_edges(G2) == 1); + // num_vertices stays the same + BOOST_CHECK(num_vertices(G0) == 3); + BOOST_CHECK(num_vertices(G1) == 2); + BOOST_CHECK(num_vertices(G2) == 2); + + // add edge to G0 without propagation + add_edge(1, 2, G0); + + BOOST_CHECK(num_edges(G0) == 2); + BOOST_CHECK(num_edges(G1) == 1); + BOOST_CHECK(num_edges(G2) == 1); + // num_vertices stays the same + BOOST_CHECK(num_vertices(G0) == 3); + BOOST_CHECK(num_vertices(G1) == 2); + BOOST_CHECK(num_vertices(G2) == 2); + + // add vertex 2 to G2/G1 with edge propagation + Vertex n = add_vertex(2, G2); + BOOST_CHECK(G2.local_to_global(n) == 2); + + BOOST_CHECK(num_edges(G0) == 2); + BOOST_CHECK(num_edges(G1) == 2); + BOOST_CHECK(num_edges(G2) == 2); + // num_vertices stays the same + BOOST_CHECK(num_vertices(G0) == 3); + BOOST_CHECK(num_vertices(G1) == 3); + BOOST_CHECK(num_vertices(G2) == 3); + + // add edge to G2 with propagation upwards + add_edge(0, 2, G2); + + BOOST_CHECK(num_edges(G0) == 3); + BOOST_CHECK(num_edges(G1) == 3); + BOOST_CHECK(num_edges(G2) == 3); + // num_vertices stays the same + BOOST_CHECK(num_vertices(G0) == 3); + BOOST_CHECK(num_vertices(G1) == 3); + BOOST_CHECK(num_vertices(G2) == 3); + + typedef std::map::vertex_descriptor, graph_traits::vertex_descriptor>::iterator v_itr; + + std::cerr << "All G0 vertices: " << std::endl; + for(v_itr v = G0.m_local_vertex.begin(); v != G0.m_local_vertex.end(); ++v) { + std::cerr << G0.local_to_global(v->first) << std::endl; + } + std::cerr << "All G1 vertices: " << std::endl; + for(v_itr v = G1.m_local_vertex.begin(); v != G1.m_local_vertex.end(); ++v) { + std::cerr << G1.local_to_global(v->first) << std::endl; + } + std::cerr << "All G2 vertices: " << std::endl; + for(v_itr v = G2.m_local_vertex.begin(); v != G2.m_local_vertex.end(); ++v) { + std::cerr << G2.local_to_global(v->first) << std::endl; + } + std::cerr << "All G0 edges: " << std::endl; + BGL_FORALL_EDGES(e, G0, Graph) { + std::cerr << source(e, G0) << "->" << target(e, G0) << std::endl; + } + std::cerr << "All G1 edges: " << std::endl; + BGL_FORALL_EDGES(e, G1, Graph) { + std::cerr << source(e, G1) << "->" << target(e, G1) << std::endl; + } + std::cerr << "All G2 edges: " << std::endl; + BGL_FORALL_EDGES(e, G2, Graph) { + std::cerr << source(e, G2) << "->" << target(e, G2) << std::endl; + } +}