// r_c_shortest_paths.hpp header file | |
// 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) | |
#ifndef BOOST_GRAPH_R_C_SHORTEST_PATHS_HPP | |
#define BOOST_GRAPH_R_C_SHORTEST_PATHS_HPP | |
#include <map> | |
#include <queue> | |
#include <vector> | |
#include <boost/graph/graph_traits.hpp> | |
namespace boost { | |
// r_c_shortest_paths_label struct | |
template<class Graph, class Resource_Container> | |
struct r_c_shortest_paths_label | |
{ | |
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<Graph>::edge_descriptor& ed = | |
graph_traits<Graph>::edge_descriptor(), | |
const typename graph_traits<Graph>::vertex_descriptor& vd = | |
graph_traits<Graph>::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 ) | |
return *this; | |
this->~r_c_shortest_paths_label(); | |
new( this ) r_c_shortest_paths_label( other ); | |
return *this; | |
} | |
const unsigned long num; | |
Resource_Container cumulated_resource_consumption; | |
const r_c_shortest_paths_label* const p_pred_label; | |
const typename graph_traits<Graph>::edge_descriptor pred_edge; | |
const typename graph_traits<Graph>::vertex_descriptor resident_vertex; | |
bool b_is_dominated; | |
bool b_is_processed; | |
}; // r_c_shortest_paths_label | |
template<class Graph, class Resource_Container> | |
inline bool operator== | |
( const r_c_shortest_paths_label<Graph, Resource_Container>& l1, | |
const r_c_shortest_paths_label<Graph, Resource_Container>& l2 ) | |
{ | |
return | |
l1.cumulated_resource_consumption == l2.cumulated_resource_consumption; | |
} | |
template<class Graph, class Resource_Container> | |
inline bool operator!= | |
( const r_c_shortest_paths_label<Graph, Resource_Container>& l1, | |
const r_c_shortest_paths_label<Graph, Resource_Container>& l2 ) | |
{ | |
return | |
!( l1 == l2 ); | |
} | |
template<class Graph, class Resource_Container> | |
inline bool operator< | |
( const r_c_shortest_paths_label<Graph, Resource_Container>& l1, | |
const r_c_shortest_paths_label<Graph, Resource_Container>& l2 ) | |
{ | |
return | |
l1.cumulated_resource_consumption < l2.cumulated_resource_consumption; | |
} | |
template<class Graph, class Resource_Container> | |
inline bool operator> | |
( const r_c_shortest_paths_label<Graph, Resource_Container>& l1, | |
const r_c_shortest_paths_label<Graph, Resource_Container>& l2 ) | |
{ | |
return | |
l2.cumulated_resource_consumption < l1.cumulated_resource_consumption; | |
} | |
template<class Graph, class Resource_Container> | |
inline bool operator<= | |
( const r_c_shortest_paths_label<Graph, Resource_Container>& l1, | |
const r_c_shortest_paths_label<Graph, Resource_Container>& l2 ) | |
{ | |
return | |
l1 < l2 || l1 == l2; | |
} | |
template<class Graph, class Resource_Container> | |
inline bool operator>= | |
( const r_c_shortest_paths_label<Graph, Resource_Container>& l1, | |
const r_c_shortest_paths_label<Graph, Resource_Container>& l2 ) | |
{ | |
return l2 < l1 || l1 == l2; | |
} | |
namespace detail { | |
// ks_smart_pointer class | |
// from: | |
// Kuhlins, S.; Schader, M. (1999): | |
// Die C++-Standardbibliothek | |
// Springer, Berlin | |
// p. 333 f. | |
template<class T> | |
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 | |
// r_c_shortest_paths_dispatch function (body/implementation) | |
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_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 | |
std::vector | |
<std::vector | |
<typename graph_traits | |
<Graph>::edge_descriptor> >& pareto_optimal_solutions, | |
std::vector | |
<Resource_Container>& pareto_optimal_resource_containers, | |
bool b_all_pareto_optimal_solutions, | |
// to initialize the first label/resource container | |
// and to carry the type information | |
const Resource_Container& rc, | |
Resource_Extension_Function& ref, | |
Dominance_Function& dominance, | |
// to specify the memory management strategy for the labels | |
Label_Allocator /*la*/, | |
Visitor vis ) | |
{ | |
pareto_optimal_resource_containers.clear(); | |
pareto_optimal_solutions.clear(); | |
unsigned long i_label_num = 0; | |
typedef | |
typename | |
Label_Allocator::template rebind | |
<r_c_shortest_paths_label | |
<Graph, Resource_Container> >::other LAlloc; | |
LAlloc l_alloc; | |
typedef | |
ks_smart_pointer | |
<r_c_shortest_paths_label<Graph, Resource_Container> > Splabel; | |
std::priority_queue<Splabel, std::vector<Splabel>, std::greater<Splabel> > | |
unprocessed_labels; | |
bool b_feasible = true; | |
r_c_shortest_paths_label<Graph, Resource_Container>* first_label = | |
l_alloc.allocate( 1 ); | |
l_alloc.construct | |
( first_label, | |
r_c_shortest_paths_label | |
<Graph, Resource_Container>( i_label_num++, | |
rc, | |
0, | |
typename graph_traits<Graph>:: | |
edge_descriptor(), | |
s ) ); | |
Splabel splabel_first_label = Splabel( first_label ); | |
unprocessed_labels.push( splabel_first_label ); | |
std::vector<std::list<Splabel> > vec_vertex_labels( num_vertices( g ) ); | |
vec_vertex_labels[vertex_index_map[s]].push_back( splabel_first_label ); | |
std::vector<typename std::list<Splabel>::iterator> | |
vec_last_valid_positions_for_dominance( num_vertices( g ) ); | |
for( int i = 0; i < static_cast<int>( num_vertices( g ) ); ++i ) | |
vec_last_valid_positions_for_dominance[i] = vec_vertex_labels[i].begin(); | |
std::vector<int> vec_last_valid_index_for_dominance( num_vertices( g ), 0 ); | |
std::vector<bool> | |
b_vec_vertex_already_checked_for_dominance( num_vertices( g ), false ); | |
while( unprocessed_labels.size() ) | |
{ | |
Splabel cur_label = unprocessed_labels.top(); | |
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<Splabel> 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 | |
// 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 | |
// if the label to be extended is undominated | |
if( !cur_label->b_is_dominated ) | |
{ | |
int i_cur_resident_vertex_num = cur_label->resident_vertex; | |
std::list<Splabel>& list_labels_cur_vertex = | |
vec_vertex_labels[i_cur_resident_vertex_num]; | |
if( static_cast<int>( list_labels_cur_vertex.size() ) >= 2 | |
&& vec_last_valid_index_for_dominance[i_cur_resident_vertex_num] | |
< static_cast<int>( list_labels_cur_vertex.size() ) ) | |
{ | |
typename std::list<Splabel>::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; | |
typename std::list<Splabel>::iterator inner_iter = outer_iter; | |
if( !b_outer_iter_at_or_beyond_last_valid_pos_for_dominance | |
&& outer_iter == | |
vec_last_valid_positions_for_dominance | |
[i_cur_resident_vertex_num] ) | |
b_outer_iter_at_or_beyond_last_valid_pos_for_dominance = true; | |
if( !b_vec_vertex_already_checked_for_dominance | |
[i_cur_resident_vertex_num] | |
|| b_outer_iter_at_or_beyond_last_valid_pos_for_dominance ) | |
{ | |
++inner_iter; | |
} | |
else | |
{ | |
inner_iter = | |
vec_last_valid_positions_for_dominance | |
[i_cur_resident_vertex_num]; | |
++inner_iter; | |
} | |
bool b_outer_iter_erased = false; | |
while( inner_iter != list_labels_cur_vertex.end() ) | |
{ | |
Splabel cur_inner_splabel = *inner_iter; | |
if( dominance( cur_outer_splabel-> | |
cumulated_resource_consumption, | |
cur_inner_splabel-> | |
cumulated_resource_consumption ) ) | |
{ | |
typename std::list<Splabel>::iterator buf = inner_iter; | |
++inner_iter; | |
list_labels_cur_vertex.erase( buf ); | |
if( cur_inner_splabel->b_is_processed ) | |
{ | |
l_alloc.destroy( cur_inner_splabel.get() ); | |
l_alloc.deallocate( cur_inner_splabel.get(), 1 ); | |
} | |
else | |
cur_inner_splabel->b_is_dominated = true; | |
continue; | |
} | |
else | |
++inner_iter; | |
if( dominance( cur_inner_splabel-> | |
cumulated_resource_consumption, | |
cur_outer_splabel-> | |
cumulated_resource_consumption ) ) | |
{ | |
typename std::list<Splabel>::iterator buf = outer_iter; | |
++outer_iter; | |
list_labels_cur_vertex.erase( buf ); | |
b_outer_iter_erased = true; | |
if( cur_outer_splabel->b_is_processed ) | |
{ | |
l_alloc.destroy( cur_outer_splabel.get() ); | |
l_alloc.deallocate( cur_outer_splabel.get(), 1 ); | |
} | |
else | |
cur_outer_splabel->b_is_dominated = true; | |
break; | |
} | |
} | |
if( !b_outer_iter_erased ) | |
++outer_iter; | |
} | |
if( static_cast<int>( list_labels_cur_vertex.size() ) > 1 ) | |
vec_last_valid_positions_for_dominance[i_cur_resident_vertex_num] = | |
(--(list_labels_cur_vertex.end())); | |
else | |
vec_last_valid_positions_for_dominance[i_cur_resident_vertex_num] = | |
list_labels_cur_vertex.begin(); | |
b_vec_vertex_already_checked_for_dominance | |
[i_cur_resident_vertex_num] = true; | |
vec_last_valid_index_for_dominance[i_cur_resident_vertex_num] = | |
static_cast<int>( list_labels_cur_vertex.size() ) - 1; | |
} | |
} | |
if( !b_all_pareto_optimal_solutions && cur_label->resident_vertex == t ) | |
{ | |
// the devil don't sleep | |
if( cur_label->b_is_dominated ) | |
{ | |
l_alloc.destroy( cur_label.get() ); | |
l_alloc.deallocate( cur_label.get(), 1 ); | |
} | |
while( unprocessed_labels.size() ) | |
{ | |
Splabel l = unprocessed_labels.top(); | |
unprocessed_labels.pop(); | |
// delete only dominated labels, because nondominated labels are | |
// deleted at the end of the function | |
if( l->b_is_dominated ) | |
{ | |
l_alloc.destroy( l.get() ); | |
l_alloc.deallocate( l.get(), 1 ); | |
} | |
} | |
break; | |
} | |
if( !cur_label->b_is_dominated ) | |
{ | |
cur_label->b_is_processed = true; | |
vis.on_label_not_dominated( *cur_label, g ); | |
typename graph_traits<Graph>::vertex_descriptor cur_vertex = | |
cur_label->resident_vertex; | |
typename graph_traits<Graph>::out_edge_iterator 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<Graph, Resource_Container>* new_label = | |
l_alloc.allocate( 1 ); | |
l_alloc.construct( new_label, | |
r_c_shortest_paths_label | |
<Graph, Resource_Container> | |
( 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, | |
new_label->pred_edge ); | |
if( !b_feasible ) | |
{ | |
vis.on_label_not_feasible( *new_label, g ); | |
l_alloc.destroy( new_label ); | |
l_alloc.deallocate( new_label, 1 ); | |
} | |
else | |
{ | |
const r_c_shortest_paths_label<Graph, Resource_Container>& | |
ref_new_label = *new_label; | |
vis.on_label_feasible( ref_new_label, g ); | |
Splabel new_sp_label( new_label ); | |
vec_vertex_labels[vertex_index_map[new_sp_label->resident_vertex]]. | |
push_back( new_sp_label ); | |
unprocessed_labels.push( new_sp_label ); | |
} | |
} | |
} | |
else | |
{ | |
vis.on_label_dominated( *cur_label, g ); | |
l_alloc.destroy( cur_label.get() ); | |
l_alloc.deallocate( cur_label.get(), 1 ); | |
} | |
} | |
std::list<Splabel> dsplabels = vec_vertex_labels[vertex_index_map[t]]; | |
typename std::list<Splabel>::const_iterator csi = dsplabels.begin(); | |
typename std::list<Splabel>::const_iterator csi_end = dsplabels.end(); | |
// if d could be reached from o | |
if( dsplabels.size() ) | |
{ | |
for( ; csi != csi_end; ++csi ) | |
{ | |
std::vector<typename graph_traits<Graph>::edge_descriptor> | |
cur_pareto_optimal_path; | |
const r_c_shortest_paths_label<Graph, Resource_Container>* p_cur_label = | |
(*csi).get(); | |
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; | |
} | |
pareto_optimal_solutions.push_back( cur_pareto_optimal_path ); | |
if( !b_all_pareto_optimal_solutions ) | |
break; | |
} | |
} | |
int i_size = static_cast<int>( vec_vertex_labels.size() ); | |
for( int i = 0; i < i_size; ++i ) | |
{ | |
const std::list<Splabel>& 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 ) | |
{ | |
l_alloc.destroy( (*csi).get() ); | |
l_alloc.deallocate( (*csi).get(), 1 ); | |
} | |
} | |
} // r_c_shortest_paths_dispatch | |
} // detail | |
// default_r_c_shortest_paths_visitor struct | |
struct default_r_c_shortest_paths_visitor | |
{ | |
template<class Label, class Graph> | |
void on_label_popped( const Label&, const Graph& ) {} | |
template<class Label, class Graph> | |
void on_label_feasible( const Label&, const Graph& ) {} | |
template<class Label, class Graph> | |
void on_label_not_feasible( const Label&, const Graph& ) {} | |
template<class Label, class Graph> | |
void on_label_dominated( const Label&, const Graph& ) {} | |
template<class Label, class Graph> | |
void on_label_not_dominated( const Label&, const Graph& ) {} | |
}; // 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 | |
// 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, | |
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_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<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 ) | |
{ | |
// 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; | |
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]; | |
pareto_optimal_resource_container = pareto_optimal_resource_containers[0]; | |
} | |
} | |
// 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_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<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 ) | |
{ | |
// 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; | |
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]; | |
pareto_optimal_resource_container = pareto_optimal_resource_containers[0]; | |
} | |
} | |
// r_c_shortest_paths | |
// check_r_c_path function | |
template<class Graph, | |
class Resource_Container, | |
class Resource_Extension_Function> | |
void check_r_c_path( const Graph& g, | |
const std::vector | |
<typename graph_traits | |
<Graph>::edge_descriptor>& ed_vec_path, | |
const Resource_Container& initial_resource_levels, | |
// if true, computed accumulated final resource levels must | |
// be equal to desired_final_resource_levels | |
// 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<Graph>::edge_descriptor& | |
ed_last_extended_arc ) | |
{ | |
int i_size_ed_vec_path = static_cast<int>( ed_vec_path.size() ); | |
std::vector<typename graph_traits<Graph>::edge_descriptor> buf_path; | |
if( i_size_ed_vec_path == 0 ) | |
b_feasible = true; | |
else | |
{ | |
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 | |
for( int i = i_size_ed_vec_path - 1; i >= 0; --i ) | |
buf_path.push_back( ed_vec_path[i] ); | |
for( int i = 0; i < i_size_ed_vec_path - 1; ++i ) | |
{ | |
if( target( buf_path[i], g ) != source( buf_path[i + 1], g ) ) | |
{ | |
b_is_a_path_at_all = false; | |
b_feasible = false; | |
b_correctly_extended = false; | |
return; | |
} | |
} | |
} | |
b_is_a_path_at_all = true; | |
b_feasible = true; | |
b_correctly_extended = false; | |
Resource_Container current_resource_levels = initial_resource_levels; | |
actual_final_resource_levels = current_resource_levels; | |
for( int 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, | |
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 ? | |
true : false; | |
else | |
{ | |
if( actual_final_resource_levels < desired_final_resource_levels | |
|| actual_final_resource_levels == desired_final_resource_levels ) | |
b_correctly_extended = true; | |
} | |
} // check_path | |
} // namespace | |
#endif // BOOST_GRAPH_R_C_SHORTEST_PATHS_HPP |