diff --git a/bcp_cvrptw.cpp b/bcp_cvrptw.cpp index 7ed0ac82ab77ad859a804b373e47198fe3c0728f..b840e9a56d0d6724b2072617579cf5eb635ad9d8 100644 --- a/bcp_cvrptw.cpp +++ b/bcp_cvrptw.cpp @@ -3118,33 +3118,35 @@ c_PricingSolverCVRPTW::c_PricingSolverCVRPTW( c_Controller* controller, int netw vector<bool> dominanceNodes_Fw = vector<bool>(ctlr->NumVertices()); //vector<bool> dominanceNodes_Bw = vector<bool>(ctlr->NumVertices()); - if( taskNetwork && ctlr->RestrictVerticesWithDominanceCheck() ){ - dominanceNodes_Fw[0] = true; - //dominanceNodes_Bw[0] = true; - for( int i = 1; i < ctlr->NumVertices()-1; i++ ){ - //Fw take only the vertex of each customer which belongs to the current day - dominanceNodes_Fw[i] = ctlr->GetDay(i) == i_day ? true : false; - //Bw: there may be several entering vertices of a customer in a specific day network, check if arc from vertex to dest depot exists - /*if( ctlr->ArcExistsOnDay( i, ctlr->DestDepotVertex(), i_day)){ - dominanceNodes_Bw[i] = true; - } else{ - dominanceNodes_Bw[i] = false; - }*/ - } - dominanceNodes_Fw[ctlr->NumVertices()-1] = true; - //dominanceNodes_Bw[ctlr->NumVertices()-1] = true; - - o_esppc_solver.setDominanceNodes_FW(dominanceNodes_Fw); - //o_esppc_solver.setDominanceNodes_BW(dominanceNodes_Bw); - } else{ - for( int i = 0; i < ctlr->NumVertices(); i++ ){ - dominanceNodes_Fw[i] = true; - //dominanceNodes_Bw[i] = true; - } - o_esppc_solver.setDominanceNodes_FW(dominanceNodes_Fw); - //o_esppc_solver.setDominanceNodes_BW(dominanceNodes_Bw); - } + //-->CT:New version of solver does not have setDominanceNodes_FW + //if( taskNetwork && ctlr->RestrictVerticesWithDominanceCheck() ){ + // dominanceNodes_Fw[0] = true; + // //dominanceNodes_Bw[0] = true; + // for( int i = 1; i < ctlr->NumVertices()-1; i++ ){ + // //Fw take only the vertex of each customer which belongs to the current day + // dominanceNodes_Fw[i] = ctlr->GetDay(i) == i_day ? true : false; + // //Bw: there may be several entering vertices of a customer in a specific day network, check if arc from vertex to dest depot exists + // /*if( ctlr->ArcExistsOnDay( i, ctlr->DestDepotVertex(), i_day)){ + // dominanceNodes_Bw[i] = true; + // } else{ + // dominanceNodes_Bw[i] = false; + // }*/ + // } + // dominanceNodes_Fw[ctlr->NumVertices()-1] = true; + // //dominanceNodes_Bw[ctlr->NumVertices()-1] = true; + + // o_esppc_solver.setDominanceNodes_FW(dominanceNodes_Fw); + // //o_esppc_solver.setDominanceNodes_BW(dominanceNodes_Bw); + //} else{ + // for( int i = 0; i < ctlr->NumVertices(); i++ ){ + // dominanceNodes_Fw[i] = true; + // //dominanceNodes_Bw[i] = true; + // } + // o_esppc_solver.setDominanceNodes_FW(dominanceNodes_Fw); + // //o_esppc_solver.setDominanceNodes_BW(dominanceNodes_Bw); + //} + //<- } void c_PricingSolverCVRPTW::Update( c_BranchAndBoundNode* node ) diff --git a/bcp_cvrptw.h b/bcp_cvrptw.h index d7463de657bae05b2040fdfe3ab2172a3f56042a..7814a2af1020478221e47e2a38ab5bbdd206baf5 100644 --- a/bcp_cvrptw.h +++ b/bcp_cvrptw.h @@ -3,7 +3,7 @@ #include "ColumnGeneration/base.h" -#include "ESPPRC/bucket_mgnt.h" +#include "ESPPRC/extension_mgnt.h" #include "ESPPRC/dominance_mgnt.h" #include "ESPPRC/label.h" #include "ESPPRC/solver.h" @@ -530,10 +530,10 @@ public: }; //typedef c_Bucket_Manager_UsingVector<c_LabelCVRPTW_Fw , true> BManagerFW; -typedef c_Bucket_Manager<c_LabelCVRPTW_Fw , true> BManagerFW; +typedef c_Extension_Manager<c_LabelCVRPTW_Fw, true> ExtManagerFW; typedef c_Dominance_Manager<c_LabelCVRPTW_Fw> DManagerFW; //typedef c_Bucket_Manager_UsingVector<c_LabelCVRPTW_Bw, false> BManagerBW; -typedef c_Bucket_Manager<c_LabelCVRPTW_Bw, false> BManagerBW; +typedef c_Extension_Manager<c_LabelCVRPTW_Bw, false> ExtManagerBW; typedef c_Dominance_Manager<c_LabelCVRPTW_Bw> DManagerBW; class c_MergeManagerCVRPTW { @@ -569,7 +569,7 @@ class c_PricingSolverCVRPTW : public c_PricingProblem { int i_day; bool b_exactDom; c_MergeManagerCVRPTW o_merger; - c_SPPRC_Solver<c_REF_CVRPTW,BManagerFW,DManagerFW,BManagerBW,DManagerBW,c_MergeManagerCVRPTW> o_esppc_solver; + c_SPPRC_Solver<c_REF_CVRPTW, ExtManagerFW, DManagerFW, ExtManagerBW, DManagerBW, c_MergeManagerCVRPTW> o_esppc_solver; public: typedef c_LabelCVRPTW_Fw tLabel_Fw; typedef c_LabelCVRPTW_Bw tLabel_Bw; diff --git a/espprc/bucket_mgnt.h b/espprc/bucket_mgnt.h deleted file mode 100644 index d17c431c9071551ee9d0200e2859635abc203063..0000000000000000000000000000000000000000 --- a/espprc/bucket_mgnt.h +++ /dev/null @@ -1,595 +0,0 @@ -#ifndef ESPPTW_BUCKET_MGNT_H -#define ESPPTW_BUCKET_MGNT_H - -#include <iostream> -#include <vector> -#include <map> -#include <unordered_map> - -///////////////////////////////////////////////////////////////////////////// -// c_Bucket_Manager_ESPPC -///////////////////////////////////////////////////////////////////////////// -namespace espprc -{ - -/* This is the only implementation of a bucket manager that can handle REFs with increase 0 in the critical - resource defining the bucket index. It is guaranteed that for identical critical resource values a label - with smaller ID is extended before any other label with larger ID (same critical resource). - */ -template <class Label, bool increasingRes> -class c_Bucket_Manager { -protected: - int i_curr_bucket_idx; - std::vector<std::vector<Label*> > o_buckets; - bool b_invoke_dom_alg; - std::vector<int> v_position; // position for label id - // statistics - int i_added_labels; - int i_erased_labels; - int i_pos_in_curr_bucket; - - //singly linked list (and counter) for labels that are dominated, but stored because they are already extended - int i_added_labels_storedSinceExtended; - Label* p_first_label_storedSinceExtended; -public: - c_Bucket_Manager(); - typedef Label tLabel; - - void insert( Label* ); - void erase( Label* ); - Label* get_next(); // return and set next label to propagate - bool invoke_dominance_algorithm(); - void clear(); - void OutputInStream( std::ostream& s ) const; // IO: number of labels in current bucket - // statistics - int AddedLabels() const { return i_added_labels; } - int ErasedLabels() const { return i_erased_labels; } - int OpenLabels() const { return (i_added_labels - i_erased_labels); } - - void insertLabelStoredSinceExtended( Label* ); -}; - -template <class Label, bool increasingRes> -void espprc::c_Bucket_Manager<Label, increasingRes>::insertLabelStoredSinceExtended(Label* new_label) -{ - i_added_labels_storedSinceExtended++; - new_label->set_next( p_first_label_storedSinceExtended ); - p_first_label_storedSinceExtended = new_label; -} - -template <class Label, bool increasingRes> -void c_Bucket_Manager<Label, increasingRes>::clear() -{ - int buckets_size=(int) o_buckets.size(); - for (int i=0; i< buckets_size;i++) - o_buckets[i].clear(); - i_curr_bucket_idx=0; - b_invoke_dom_alg = true; - i_added_labels = 0; - i_erased_labels = 0; - i_pos_in_curr_bucket = 0; - - while (p_first_label_storedSinceExtended) - { - Label* help= p_first_label_storedSinceExtended; - p_first_label_storedSinceExtended=p_first_label_storedSinceExtended->next(); - delete help; - } - //if( i_added_labels_storedSinceExtended >= 10 ){ - // cout << "Num Labels Dominated although extended: " << i_added_labels_storedSinceExtended << endl; //TODO: remove! - //} - i_added_labels_storedSinceExtended = 0; -} - -// -//template <class Label, bool increasingRes> -//void c_Bucket_Manager<Label, increasingRes>::clear() -//{ -// int buckets_size=(int) o_buckets.size(); -// for (int i=0; i< buckets_size;i++) -// o_buckets[i].clear(); -// i_curr_bucket_idx=0; -// b_invoke_dom_alg = true; -// i_added_labels = 0; -// i_erased_labels = 0; -// i_pos_in_curr_bucket = 0; -//} - - -template <class Label, bool increasingRes> -void c_Bucket_Manager<Label, increasingRes>::OutputInStream(std::ostream& s) const -{ - s<< "Labels in Bucket " << i_curr_bucket_idx << ":" << o_buckets[i_curr_bucket_idx].size() <<endl; -} - - -template <class Label, bool increasingRes> -c_Bucket_Manager<Label, increasingRes>::c_Bucket_Manager() -: i_curr_bucket_idx (0), - b_invoke_dom_alg(true), - i_added_labels(0), - i_erased_labels(0), - i_pos_in_curr_bucket(0), - i_added_labels_storedSinceExtended(0), - p_first_label_storedSinceExtended(NULL) -{} - - -template <class Label, bool increasingRes> -bool c_Bucket_Manager<Label, increasingRes>::invoke_dominance_algorithm() -{ - return true; - if ( b_invoke_dom_alg ) - { - b_invoke_dom_alg = false; - return true; - } - return false; -} - - -//Jean-Bertrand's version -template <class Label, bool increasingRes> -Label* c_Bucket_Manager<Label, increasingRes>::get_next() -{ - if (increasingRes) - { - int obucketsize = (int)o_buckets.size(); - if (i_pos_in_curr_bucket >= (int)o_buckets[i_curr_bucket_idx].size()) - { - o_buckets[i_curr_bucket_idx].clear(); - i_pos_in_curr_bucket = 0; - b_invoke_dom_alg = true; - do - { - if (++i_curr_bucket_idx >= obucketsize) return nullptr; - } while (o_buckets[i_curr_bucket_idx].empty()); - } - - while (!(o_buckets[i_curr_bucket_idx][i_pos_in_curr_bucket])) - { - if (++i_pos_in_curr_bucket >= (int)o_buckets[i_curr_bucket_idx].size()) - { - o_buckets[i_curr_bucket_idx].clear(); - i_pos_in_curr_bucket = 0; - b_invoke_dom_alg = true; - do - { - if (++i_curr_bucket_idx >= obucketsize) return nullptr; - } while (o_buckets[i_curr_bucket_idx].empty()); - } - } - } - else - { - if (i_pos_in_curr_bucket >= (int)o_buckets[i_curr_bucket_idx].size()) - { - o_buckets[i_curr_bucket_idx].clear(); - i_pos_in_curr_bucket = 0; - b_invoke_dom_alg = true; - do - { - if (--i_curr_bucket_idx < 0) return nullptr; - } while (o_buckets[i_curr_bucket_idx].empty()); - } - - while (!(o_buckets[i_curr_bucket_idx][i_pos_in_curr_bucket])) - { - if (++i_pos_in_curr_bucket >= (int)o_buckets[i_curr_bucket_idx].size()) - { - o_buckets[i_curr_bucket_idx].clear(); - i_pos_in_curr_bucket = 0; - b_invoke_dom_alg = true; - do - { - if (--i_curr_bucket_idx < 0) return nullptr; - } while (o_buckets[i_curr_bucket_idx].empty()); - } - } - } - - Label* ret = o_buckets[i_curr_bucket_idx][i_pos_in_curr_bucket]; - ++i_pos_in_curr_bucket; - ++i_erased_labels; - return ret; -} - - - - - - -//template <class Label, bool increasingRes> -//Label* c_Bucket_Manager<Label, increasingRes>::get_next() -//{ -// Label* ret = nullptr; -// while (i_pos_in_curr_bucket >= (int) o_buckets[i_curr_bucket_idx].size()) -// { -// o_buckets[i_curr_bucket_idx].clear(); -// i_pos_in_curr_bucket = 0; -// if (increasingRes) -// i_curr_bucket_idx++; -// else -// i_curr_bucket_idx--; -// b_invoke_dom_alg = true; -// // nothing left? -// if (i_curr_bucket_idx < 0 || i_curr_bucket_idx >= (int)o_buckets.size()) -// return nullptr; -// } -// while (!(o_buckets[i_curr_bucket_idx][i_pos_in_curr_bucket])) -// { -// i_pos_in_curr_bucket++; -// if (i_pos_in_curr_bucket >= (int) o_buckets[i_curr_bucket_idx].size()) -// { -// o_buckets[i_curr_bucket_idx].clear(); -// i_pos_in_curr_bucket = 0; -// if (increasingRes) -// i_curr_bucket_idx++; -// else -// i_curr_bucket_idx--; -// b_invoke_dom_alg = true; -// if (i_curr_bucket_idx < 0 || i_curr_bucket_idx >= (int)o_buckets.size()) //added by Anka: situation with o_buckets.size() == i_curr_bucket_idx occured in next loop and caused exception -// return nullptr; -// while (i_pos_in_curr_bucket >= (int) o_buckets[i_curr_bucket_idx].size()) -// { -// o_buckets[i_curr_bucket_idx].clear(); -// i_pos_in_curr_bucket = 0; -// if (increasingRes) -// i_curr_bucket_idx++; -// else -// i_curr_bucket_idx--; -// b_invoke_dom_alg = true; -// if (i_curr_bucket_idx < 0 || i_curr_bucket_idx >= (int)o_buckets.size()) -// return nullptr; -// } -// } -// } -// ret = o_buckets[i_curr_bucket_idx][i_pos_in_curr_bucket]; -// i_pos_in_curr_bucket++; -// i_erased_labels++; -// return ret; -//} - - -template <class Label, bool increasingRes> -void c_Bucket_Manager<Label, increasingRes>::erase( Label* label ) -{ - if ((int)v_position.size() <= label->Id()) - return; - i_erased_labels++; - int idx=v_position[label->Id()]; - int res_val = (*label)(); - if (idx>-1) - o_buckets[res_val][idx]=nullptr; -} - - -// insert element to bucket container -template <class Label, bool increasingRes> -void c_Bucket_Manager<Label, increasingRes>::insert( Label* label ) -{ - i_added_labels++; - int res_val = (*label)(); - if( increasingRes ) - { - //for an increasing resource, extend the bucket-container - if ( res_val >= (int)o_buckets.size() ) - o_buckets.resize( 2*res_val+1 ); - } - else - { - //set the current bucket index to the end, when insert is done for the first time - if ( res_val >= (int)o_buckets.size() ) - o_buckets.resize( res_val+1 ); - //decreasing resource can never be less than the current bucket index, but when a new pricing iteration is started - if( res_val > i_curr_bucket_idx ) - i_curr_bucket_idx = res_val; - } - int idx=(int) o_buckets[res_val].size(); - o_buckets[res_val].push_back(label); - if ((int)v_position.size()<=label->Id()) - { - v_position.resize(2*label->Id()+1,-1); - } - v_position[label->Id()]=idx; -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////////// - -template <class Label, bool increasingRes> -class c_Bucket_Manager_UsingUnorderedMap { -protected: - int i_curr_bucket_idx; - std::vector<std::unordered_map<int,Label*> > o_buckets; - bool b_invoke_dom_alg; - // statistics - int i_added_labels; - int i_erased_labels; - -public: - c_Bucket_Manager_UsingUnorderedMap(); - typedef Label tLabel; - - void insert( Label* ); - void erase( Label* ); - Label* get_next(); // return and set next label to propagate - bool invoke_dominance_algorithm(); - void clear(); - void OutputInStream( std::ostream& s ) const; // IO: number of labels in current bucket - // statistics - int AddedLabels() const { return i_added_labels; } - int ErasedLabels() const { return i_erased_labels; } - int OpenLabels() const { return (i_added_labels - i_erased_labels); } -}; - - -template <class Label, bool increasingRes> -void c_Bucket_Manager_UsingUnorderedMap<Label, increasingRes>::clear() -{ - int buckets_size=(int) o_buckets.size(); - for (int i=0; i< buckets_size;i++) - o_buckets[i].clear(); - i_curr_bucket_idx=0; - i_added_labels = 0; - i_erased_labels = 0; - b_invoke_dom_alg = true; -} - - -template <class Label, bool increasingRes> -void c_Bucket_Manager_UsingUnorderedMap<Label, increasingRes>::OutputInStream(std::ostream& s) const -{ - s<< "Labels in Bucket " << i_curr_bucket_idx << ":" << o_buckets[i_curr_bucket_idx].size() <<endl; -} - - -template <class Label, bool increasingRes> -c_Bucket_Manager_UsingUnorderedMap<Label, increasingRes>::c_Bucket_Manager_UsingUnorderedMap() -: i_curr_bucket_idx (0), - b_invoke_dom_alg(true), - i_added_labels(0), - i_erased_labels(0) -{} - - -template <class Label, bool increasingRes> -bool c_Bucket_Manager_UsingUnorderedMap<Label, increasingRes>::invoke_dominance_algorithm() -{ - if ( b_invoke_dom_alg ) - { - b_invoke_dom_alg = false; - return true; - } - return false; -} - - -template <class Label, bool increasingRes> -Label* c_Bucket_Manager_UsingUnorderedMap<Label, increasingRes>::get_next() -{ - Label* ret = nullptr; - while (!ret) - { - if(increasingRes) - { - while ( i_curr_bucket_idx<(int)o_buckets.size() && o_buckets[i_curr_bucket_idx].empty() ) - i_curr_bucket_idx++; - } - else - { - while ( i_curr_bucket_idx >= 0 && o_buckets[i_curr_bucket_idx].empty() ) - i_curr_bucket_idx--; - } - // nothing left? - if ( i_curr_bucket_idx < 0 || i_curr_bucket_idx >= (int)o_buckets.size() ) - return nullptr; - // otherwise erase and return first element - unordered_map<int,Label*>& the_bucket = o_buckets[i_curr_bucket_idx]; - ret = the_bucket.begin()->second; - the_bucket.erase( ret->Id() ); - // Find out if the next non-null label is still in the same bucket - // If not, invoke the dominance algorithm - if ( the_bucket.empty() ) - b_invoke_dom_alg = true; - } - //not necessary to increase erased labels, because function erase is called before! - return ret; -} - - -template <class Label, bool increasingRes> -void c_Bucket_Manager_UsingUnorderedMap<Label, increasingRes>::erase( Label* label ) -{ - i_erased_labels++; - int res_val = (*label)(); - o_buckets[res_val].erase( label->Id() ); -} - - -// insert element to bucket container -template <class Label, bool increasingRes> -void c_Bucket_Manager_UsingUnorderedMap<Label, increasingRes>::insert( Label* label ) -{ - i_added_labels++; - int res_val = (*label)(); - if( increasingRes ) - { - //for an increasing resource, extend the bucket-container - if ( res_val >= (int)o_buckets.size() ) - o_buckets.resize( 2*res_val+1 ); - } - else - { - //set the current bucket index to the end, when insert is done for the first time - if ( res_val >= (int)o_buckets.size() ) - o_buckets.resize( res_val+1 ); - //decreasing resource can never be less than the current bucket index, but when a new pricing iteration is started - if( res_val > i_curr_bucket_idx ) - i_curr_bucket_idx = res_val; - } - int id = label->Id(); - o_buckets[res_val].insert( make_pair(id,label) ); -} - - - -//////////////////////////////////////////////////////////////////////////////////////////////////////////// - - -///////////////////////////////////////////////////////////////////////////// -// c_Bucket_Manager_ESPPC_old -///////////////////////////////////////////////////////////////////////////// - - template <class Label, bool increasingRes> - class c_Bucket_Manager_UsingVector { - protected: - int i_curr_bucket_idx; - std::vector<std::vector<Label*> > o_buckets; - bool b_invoke_dom_alg; - std::vector<int> v_position; // position for label id - // statistics - int i_added_labels; - int i_erased_labels; - public: - c_Bucket_Manager_UsingVector(); - typedef Label tLabel; - - void insert(Label*); - void erase(Label*); - Label* get_next(); // return and set next label to propagate - bool invoke_dominance_algorithm(); - void clear(); - void OutputInStream(std::ostream& s) const; // IO: number of labels in current bucket - // statistics - int AddedLabels() const { return i_added_labels; } - int ErasedLabels() const { return i_erased_labels; } - int OpenLabels() const { return (i_added_labels - i_erased_labels); } - }; - - - template <class Label, bool increasingRes> - void c_Bucket_Manager_UsingVector<Label, increasingRes>::clear() - { - int buckets_size = (int)o_buckets.size(); - for (int i = 0; i < buckets_size; i++) - o_buckets[i].clear(); - i_curr_bucket_idx = 0; - b_invoke_dom_alg = true; - i_added_labels = 0; - i_erased_labels = 0; - } - - - template <class Label, bool increasingRes> - void c_Bucket_Manager_UsingVector<Label, increasingRes>::OutputInStream(std::ostream& s) const - { - s << "Labels in Bucket " << i_curr_bucket_idx << ":" << o_buckets[i_curr_bucket_idx].size() << endl; - } - - - template <class Label, bool increasingRes> - c_Bucket_Manager_UsingVector<Label, increasingRes>::c_Bucket_Manager_UsingVector() - : i_curr_bucket_idx(0), - b_invoke_dom_alg(true), - i_added_labels(0), - i_erased_labels(0) - {} - - - template <class Label, bool increasingRes> - bool c_Bucket_Manager_UsingVector<Label, increasingRes>::invoke_dominance_algorithm() - { - if (b_invoke_dom_alg) - { - b_invoke_dom_alg = false; - return true; - } - return false; - } - - - template <class Label, bool increasingRes> - Label* c_Bucket_Manager_UsingVector<Label, increasingRes>::get_next() - { - Label* ret = nullptr; - while (!ret) - { - if (increasingRes) - { - while (i_curr_bucket_idx < (int)o_buckets.size() && o_buckets[i_curr_bucket_idx].empty()) - i_curr_bucket_idx++; - } - else - { - while (i_curr_bucket_idx >= 0 && o_buckets[i_curr_bucket_idx].empty()) - i_curr_bucket_idx--; - } - // nothing left? - if (i_curr_bucket_idx < 0 || i_curr_bucket_idx >= (int)o_buckets.size()) - return nullptr; - // otherwise erase and return first element - vector<Label*>& the_bucket = o_buckets[i_curr_bucket_idx]; - while (!the_bucket.empty() && !the_bucket.back()) - the_bucket.pop_back(); - if (the_bucket.empty()) - continue; - ret = the_bucket.back(); - the_bucket.pop_back(); - // Find out if the next non-null label is still in the same bucket - // If not, invoke the dominance algorithm - while (!the_bucket.empty() && !the_bucket.back()) - the_bucket.pop_back(); - if (the_bucket.empty()) - b_invoke_dom_alg = true; - } - i_erased_labels++; - return ret; - } - - - - template <class Label, bool increasingRes> - void c_Bucket_Manager_UsingVector<Label, increasingRes>::erase(Label* label) - { - i_erased_labels++; - int idx = v_position[label->Id()]; - int res_val = (*label)(); - o_buckets[res_val][idx] = nullptr; - } - - - // insert element to bucket container - template <class Label, bool increasingRes> - void c_Bucket_Manager_UsingVector<Label, increasingRes>::insert(Label* label) - { - i_added_labels++; - int res_val = (*label)(); - if (increasingRes) - { - //for an increasing resource, extend the bucket-container - if (res_val >= (int)o_buckets.size()) - o_buckets.resize(2 * res_val + 1); - } - else - { - //set the current bucket index to the end, when insert is done for the first time - if (res_val >= (int)o_buckets.size()) - o_buckets.resize(res_val + 1); - //decreasing resource can never be less than the current bucket index, but when a new pricing iteration is started - if (res_val > i_curr_bucket_idx) - i_curr_bucket_idx = res_val; - } - int idx = (int)o_buckets[res_val].size(); - o_buckets[res_val].push_back(label); - if ((int)v_position.size() <= label->Id()) - { - v_position.resize(2 * label->Id() + 1, -1); - } - v_position[label->Id()] = idx; - } - -//////////////////////////////////////////////////////////////////////////////////////////////////////////// - -}; // of namespace - -#endif // ESPPTW_BUCKET_MGNT_H \ No newline at end of file diff --git a/espprc/dominance_mgnt.h b/espprc/dominance_mgnt.h index 85bb5a26f9ffbd378b7e13d99cf7a7bbca2098d9..019e858788bb94bc53b25856bf0247ceec8bfed0 100644 --- a/espprc/dominance_mgnt.h +++ b/espprc/dominance_mgnt.h @@ -1,7 +1,10 @@ -#ifndef ESPPTW_DOMINANCE_MGNT_H -#define ESPPTW_DOMINANCE_MGNT_H +#ifndef ESPPRC_DOMINANCE_MGNT_H +#define ESPPRC_DOMINANCE_MGNT_H #include <iostream> +#include <functional> + +#include "statistics_mgnt.h" ///////////////////////////////////////////////////////////////////////////// // c_Dominance_Manager_ESPPC @@ -9,28 +12,140 @@ namespace espprc { -template <class Label> +template <class Label, class StatManager = c_EmptyStatisticsManager> class c_Dominance_Manager { +protected: + StatManager o_initial_stat; + StatManager* p_stat; Label* p_first_label; /* singly-linked list with those "old" labels on which the dominance algorithm has already been run */ Label* p_first_added_label; /* singly-linked list with "new" labels, dominance algorithm has NOT been run */ - Label* p_iterator; //to iterate over Labels - label* iter=begin() while(iter){do something iter=next()} + std::function<bool(Label*, Label*)>* f_sorter; + std::function<bool(Label*, Label*)>* f_breakingCriterion; + int i_node; int i_added_labels; + bool b_fw; + // private member functions + void Sort(Label*& start, std::function<bool(Label*, Label*)>* sorter); + // void Reverse(Label*& start); /* needed? */ public: c_Dominance_Manager(); + void SetInfo(bool fw, int node) { b_fw = fw; i_node = node; } void insert( Label* ); - Label* apply_dominance(); // return value is first label to delete - Label* apply_dominance( int labelToPayAttention ); // return value is first label to delete + Label* apply_dominance(int bm_bucket_index = -1); // return value is first label to delete + Label* apply_final_dominance(int bm_bucket_index = -1); // return value is first label to delete Label* begin(); // iterate over all undominated labels - Label* next(); + Label* next(Label* current); void clear(); int size() const { return i_added_labels; } + void OutputInStream(std::ostream& s ) const; // Output all Label of this dominance manager + void Sort( std::function<bool (Label*,Label*)>* sorter ); + void SetSortingFunction(std::function<bool(Label*, Label*)>* sorter) { f_sorter = sorter; } + void SetBreakingCriterionFunction(std::function<bool(Label*, Label*)>* breakingCriterion) { f_breakingCriterion = breakingCriterion; } + void SetStatisticsManager(StatManager& stat) { p_stat = &stat; } + StatManager& StatisticsManager() { return *p_stat; } + void PrepareForWarmstart(int currentExtensionManagerBucket) {}; +#ifdef SPPRC_CHECK_PATH + void CheckDominance(Label* label1, Label* label2); +#endif }; -template <class Label> -void c_Dominance_Manager<Label>::clear() +template <class Label, class StatManager> +c_Dominance_Manager<Label, StatManager>::c_Dominance_Manager() +: o_initial_stat(), + p_stat(&o_initial_stat), + p_first_label(nullptr), + p_first_added_label(nullptr), + f_sorter(nullptr), + f_breakingCriterion(nullptr), + i_node(0), + i_added_labels(0), + b_fw(false) +{} + + +template <class Label, class StatManager> +void c_Dominance_Manager<Label, StatManager>::Sort( std::function<bool (Label*,Label*)>* sorter ) +{ + Sort( p_first_label, sorter ); +} + + +template <class Label, class StatManager> +void c_Dominance_Manager<Label, StatManager>::Sort( Label*& from, std::function<bool (Label*,Label*)>* sorter ) +{ + // trivial cases + if ( from == nullptr || from->next() == nullptr) + return; + if ( from->next()->next() == nullptr ) // only two labels + { + if ( !(*sorter)( from, from->next() ) ) + { + Label* new_start = from->next(); + from->next()->set_next( from ); + from->set_next(nullptr); + from = new_start; + } + return; + } + // Split in the middle + int length = 0; + Label* it = from; + Label* mid = from; + while ( it ) + { + it = it->next(); + length++; + if ( length % 2 == 0 && it ) + mid = mid->next(); + } + + // Sort each part + Label* right = mid->next(); + mid->set_next(nullptr); + Sort( from, sorter ); + Sort( right, sorter ); + // Merge both parts together + Label* result = nullptr; + Label* last = nullptr; + while ( from && right ) + { + if (result == nullptr) + { + if ((*sorter)(from, right)) + result = from; + else + result = right; + } + if ( (*sorter)( from, right ) ) + { + if ( last ) + last->set_next( from ); + last = from; + from = from->next(); + } + else + { + if ( last ) + last->set_next( right ); + last = right; + right = right->next(); + } + } + // add remaining parts + if ( from ) + last->set_next( from ); + if ( right ) + last->set_next( right ); + // return resulting start label + from = result; +} + + +template <class Label, class StatManager> +void c_Dominance_Manager<Label, StatManager>::clear() { i_added_labels=0; while (p_first_label) @@ -45,33 +160,39 @@ void c_Dominance_Manager<Label>::clear() p_first_added_label=p_first_added_label->next(); delete help; } - p_first_label = NULL; - p_first_added_label = NULL; - p_iterator =NULL; + p_first_label = nullptr; + p_first_added_label = nullptr; } -template <class Label> -Label* c_Dominance_Manager<Label>::next() +template <class Label, class StatManager> +Label* c_Dominance_Manager<Label, StatManager>::next(Label* current) { - p_iterator=p_iterator->next(); - return p_iterator; + return current->next(); } -template <class Label> -Label* c_Dominance_Manager<Label>::begin() + +template <class Label, class StatManager> +Label* c_Dominance_Manager<Label, StatManager>::begin() { - p_iterator=p_first_label; - return p_iterator; + return p_first_label; } -template <class Label> -void c_Dominance_Manager<Label>::OutputInStream(std::ostream& s) const + +template <class Label, class StatManager> +void c_Dominance_Manager<Label, StatManager>::OutputInStream(std::ostream& s) const { Label* label=p_first_label; while (label) { +#ifdef SPPRC_CHECK_PATH + if (label->b_check_required) + s << "### "; +#endif label->OutputInStream(s); + s << "Id=" << label->Id(); + if (label->predecessor()) + s << " pred_Id=" << label->predecessor()->Id(); s << endl; label=label->next(); } @@ -79,9 +200,10 @@ void c_Dominance_Manager<Label>::OutputInStream(std::ostream& s) const } -template <class Label> -void c_Dominance_Manager<Label>::insert( Label* new_label ) +template <class Label, class StatManager> +void c_Dominance_Manager<Label, StatManager>::insert( Label* new_label ) { + p_stat->OnLabelInserted(b_fw,i_node); // insert into singly-linked list right at the beginning i_added_labels++; new_label->set_next( p_first_added_label ); @@ -89,13 +211,11 @@ void c_Dominance_Manager<Label>::insert( Label* new_label ) } -template <class Label> -c_Dominance_Manager<Label>::c_Dominance_Manager() -: p_first_label( NULL ), - p_first_added_label( NULL ), - p_iterator(NULL), - i_added_labels(0) -{} +template <class Label, class StatManager> +Label* c_Dominance_Manager<Label, StatManager>::apply_final_dominance(int bm_bucket_index) +{ + return apply_dominance(bm_bucket_index); +} /* Test later empirically: @@ -103,233 +223,198 @@ Test later empirically: 2. ... */ -/* return value is singly-linked list of all those labels that need to be deleted */ -template <class Label> -Label* c_Dominance_Manager<Label>::apply_dominance() +///* return value is singly-linked list of all those labels that need to be deleted */ +template <class Label, class StatManager> +Label* c_Dominance_Manager<Label, StatManager>::apply_dominance(int bm_bucket_index) { // if there are no additional labels then there are no labels in dominance - if ( !p_first_added_label ) - return NULL; - Label* ret_labels_to_del = NULL; - // dominance between old and new labels - Label* pred_old = NULL; - for ( Label* curr_old = p_first_label; curr_old; - pred_old = curr_old, curr_old = ( curr_old ? curr_old->next() : NULL ) ) + if (!p_first_added_label) + return nullptr; + Label* ret_labels_to_del = nullptr; + // sort new labels (old ones are already sorted) + if ( f_sorter ) + Sort(p_first_added_label, f_sorter); + // dominance between two new labels (quick solution: test in both directions) + Label* pred_new1 = nullptr; + for (Label* curr_new1 = p_first_added_label; + curr_new1; + pred_new1 = curr_new1, curr_new1 = (curr_new1 ? curr_new1->next() : nullptr)) { - Label* pred_new = NULL; - for ( Label* curr_new = p_first_added_label; curr_new; /**/ ) + Label* pred_new2 = curr_new1; + for (Label* curr_new2 = curr_new1->next(); curr_new2; /**/) { - if ( *curr_old <= *curr_new ) - { // old dominates new - if ( pred_new ) - pred_new->set_next( curr_new->next() ); - else - p_first_added_label = curr_new->next(); - curr_new->set_next( ret_labels_to_del ); - ret_labels_to_del = curr_new; - curr_new = ( pred_new ? pred_new->next() : p_first_added_label ); - i_added_labels--; - } - else if ( *curr_new <= *curr_old ) - { // new dominates old - if ( pred_old ) pred_old->set_next( curr_old->next() ); - else p_first_label = curr_old->next(); - curr_old->set_next( ret_labels_to_del ); - ret_labels_to_del = curr_old; - curr_old = ( pred_old ? pred_old->next() : p_first_label); - if ( curr_old == NULL ) - break; - curr_new = p_first_added_label; - pred_new = NULL; + p_stat->OnDominanceTest(b_fw,i_node); + if (*curr_new1 <= *curr_new2) + { // new1 dominates new2 +#ifdef SPPRC_CHECK_PATH + CheckDominance(curr_new1, curr_new2); +#endif + pred_new2->set_next(curr_new2->next()); + curr_new2->set_next(ret_labels_to_del); + ret_labels_to_del = curr_new2; + curr_new2 = pred_new2->next(); i_added_labels--; } - else // no dominance + else { - pred_new = curr_new; - curr_new = curr_new->next(); + p_stat->OnDominanceTest(b_fw, i_node); + if (*curr_new2 <= *curr_new1) + { // new2 dominates new1 +#ifdef SPPRC_CHECK_PATH + CheckDominance(curr_new2, curr_new1); +#endif + if (pred_new1) + pred_new1->set_next(curr_new1->next()); + else + p_first_added_label = curr_new1->next(); + curr_new1->set_next(ret_labels_to_del); + ret_labels_to_del = curr_new1; + curr_new1 = (pred_new1 ? pred_new1->next() : p_first_added_label); + curr_new2 = curr_new1->next(); + pred_new2 = curr_new1; + i_added_labels--; + } + else // no domination + { + pred_new2 = curr_new2; + curr_new2 = curr_new2->next(); + } } } } - // dominance between two new labels - Label* pred_new1 = NULL; - for ( Label* curr_new1 = p_first_added_label; - curr_new1; - pred_new1 = curr_new1, curr_new1 = ( curr_new1 ? curr_new1->next() : NULL ) ) + // old dominates new labels + Label* pred_old = nullptr; + for (Label* curr_old = p_first_label; curr_old; + pred_old = curr_old, curr_old = (curr_old ? curr_old->next() : nullptr)) { - Label* pred_new2 = curr_new1; - for ( Label* curr_new2 = curr_new1->next(); curr_new2; /**/ ) + Label* pred_new = nullptr; + for (Label* curr_new = p_first_added_label; curr_new; /**/) { - if ( *curr_new1 <= *curr_new2 ) - { // new1 dominates new2 - pred_new2->set_next( curr_new2->next() ); - curr_new2->set_next( ret_labels_to_del ); - ret_labels_to_del = curr_new2; - - curr_new2 = pred_new2->next(); - i_added_labels--; - } - else if ( *curr_new2 <= *curr_new1 ) - { // new2 dominates new1 - if ( pred_new1 ) - pred_new1->set_next( curr_new1->next() ); - else - p_first_added_label = curr_new1->next(); - curr_new1->set_next( ret_labels_to_del ); - ret_labels_to_del = curr_new1; - - curr_new1 = ( pred_new1 ? pred_new1->next() : p_first_added_label ); - curr_new2 = curr_new1->next(); - pred_new2 = curr_new1; + if (f_breakingCriterion && (*f_breakingCriterion)(curr_old, curr_new)) + break; + p_stat->OnDominanceTest(b_fw, i_node); + if (*curr_old <= *curr_new) + { // old dominates new +#ifdef SPPRC_CHECK_PATH + CheckDominance(curr_old, curr_new); +#endif + if (pred_new) + pred_new->set_next(curr_new->next()); + else + p_first_added_label = curr_new->next(); + curr_new->set_next(ret_labels_to_del); + ret_labels_to_del = curr_new; + curr_new = (pred_new ? pred_new->next() : p_first_added_label); i_added_labels--; } - else // no domination + else // no dominance { - pred_new2 = curr_new2; - curr_new2 = curr_new2->next(); + pred_new = curr_new; + curr_new = curr_new->next(); } } } - // concatenation - // pred_new1 points to the last element of the new list - if ( pred_new1 ) + // new dominates old labels + Label* pred_new = nullptr; + for (Label* curr_new = p_first_added_label; curr_new; + pred_new = curr_new, curr_new = (curr_new ? curr_new->next() : nullptr)) { - pred_new1->set_next( p_first_label ); - p_first_label = p_first_added_label; - } - p_first_added_label = NULL; - // those labels to delete - return ret_labels_to_del; -} - - - -/* return value is singly-linked list of all those labels that need to be deleted */ -template <class Label> -Label* c_Dominance_Manager<Label>::apply_dominance(int labelToPayAttention) -{ - // if there are no additional labels then there are no labels in dominance - if ( !p_first_added_label ) - return NULL; - Label* ret_labels_to_del = NULL; - // dominance between old and new labels - Label* pred_old = NULL; - for ( Label* curr_old = p_first_label; curr_old; - pred_old = curr_old, curr_old = ( curr_old ? curr_old->next() : NULL ) ) - { - Label* pred_new = NULL; - for ( Label* curr_new = p_first_added_label; curr_new; /**/ ) + Label* pred_old = nullptr; + for (Label* curr_old = p_first_label; curr_old; /**/) { - if ( *curr_old <= *curr_new ) - { // old dominates new - if( curr_new->Id() == labelToPayAttention){ - cout << "!!!!!!!!!!! Label is dominated by label " << curr_old->Id() << ": "; - Label* l = curr_old; - while( l->generator_REF() ){ - cout << l->generator_REF()->Head() << ", "; - l = const_cast<Label*>(l->predecessor()); - } - cout << endl; - /*cout << "costs: " << curr_old->Cost() << ", time: " << curr_old->Time() - << ", ll: " << curr_old->LorryLoad() << ", tl: " << curr_old->TrailerLoad() << endl; - cout << "Werte des dominierten Labels: " << "costs: " << curr_new->Cost() << ", time: " << curr_new->Time() - << ", ll: " << curr_new->LorryLoad() << ", tl: " << curr_new->TrailerLoad() << endl;*/ - //throw; - } - if ( pred_new ) - pred_new->set_next( curr_new->next() ); - else - p_first_added_label = curr_new->next(); - curr_new->set_next( ret_labels_to_del ); - ret_labels_to_del = curr_new; - curr_new = ( pred_new ? pred_new->next() : p_first_added_label ); - i_added_labels--; - } - else if ( *curr_new <= *curr_old ) + if (f_breakingCriterion && (*f_breakingCriterion)(curr_new, curr_old)) + break; + p_stat->OnDominanceTest(b_fw, i_node); + if (*curr_new <= *curr_old) { // new dominates old - if( curr_old->Id() == labelToPayAttention){ - cout << "!!!!!!!!!!!! Label is dominated by label " << curr_new->Id() << endl; - Label* l = curr_new; - while( l->generator_REF() ){ - cout << l->generator_REF()->Head() << ", "; - l = const_cast<Label*>(l->predecessor()); - } - cout << endl; - /*cout << "costs: " << curr_new->Cost() << ", time: " << curr_new->Time() - << ", ll: " << curr_new->LorryLoad() << ", tl: " << curr_new->TrailerLoad() << endl; - cout << "Werte des dominierten Labels: " << "costs: " << curr_old->Cost() << ", time: " << curr_old->Time() - << ", ll: " << curr_old->LorryLoad() << ", tl: " << curr_old->TrailerLoad() << endl;*/ - //throw; - } - if ( pred_old ) pred_old->set_next( curr_old->next() ); - else p_first_label = curr_old->next(); - curr_old->set_next( ret_labels_to_del ); +#ifdef SPPRC_CHECK_PATH + CheckDominance(curr_new, curr_old); +#endif + if (pred_old) + pred_old->set_next(curr_old->next()); + else + p_first_label = curr_old->next(); + curr_old->set_next(ret_labels_to_del); ret_labels_to_del = curr_old; - curr_old = ( pred_old ? pred_old->next() : p_first_label); - if ( curr_old == NULL ) - break; - curr_new = p_first_added_label; - pred_new = NULL; + curr_old = (pred_old ? pred_old->next() : p_first_label); i_added_labels--; } else // no dominance { - pred_new = curr_new; - curr_new = curr_new->next(); + pred_old = curr_old; + curr_old = curr_old->next(); } } } - // dominance between two new labels - Label* pred_new1 = NULL; - for ( Label* curr_new1 = p_first_added_label; - curr_new1; - pred_new1 = curr_new1, curr_new1 = ( curr_new1 ? curr_new1->next() : NULL ) ) + // concatenate + if (f_sorter && p_first_added_label && p_first_label) { - Label* pred_new2 = curr_new1; - for ( Label* curr_new2 = curr_new1->next(); curr_new2; /**/ ) + // splice (both lists are sorted) + Label* result = nullptr; + Label* last = nullptr; + while (p_first_added_label && p_first_label) { - if ( *curr_new1 <= *curr_new2 ) - { // new1 dominates new2 - pred_new2->set_next( curr_new2->next() ); - curr_new2->set_next( ret_labels_to_del ); - ret_labels_to_del = curr_new2; - - curr_new2 = pred_new2->next(); - i_added_labels--; + if (result == nullptr) + { + if ((*f_sorter)(p_first_added_label, p_first_label)) + result = p_first_added_label; + else + result = p_first_label; } - else if ( *curr_new2 <= *curr_new1 ) - { // new2 dominates new1 - if ( pred_new1 ) - pred_new1->set_next( curr_new1->next() ); - else - p_first_added_label = curr_new1->next(); - curr_new1->set_next( ret_labels_to_del ); - ret_labels_to_del = curr_new1; - - curr_new1 = ( pred_new1 ? pred_new1->next() : p_first_added_label ); - curr_new2 = curr_new1->next(); - pred_new2 = curr_new1; - i_added_labels--; + if ((*f_sorter)(p_first_added_label, p_first_label)) + { + if (last) + last->set_next(p_first_added_label); + last = p_first_added_label; + p_first_added_label = p_first_added_label->next(); } - else // no domination + else { - pred_new2 = curr_new2; - curr_new2 = curr_new2->next(); + if (last) + last->set_next(p_first_label); + last = p_first_label; + p_first_label = p_first_label->next(); } } + // add remaining parts + if (p_first_added_label) + last->set_next(p_first_added_label); + if (p_first_label) + last->set_next(p_first_label); + p_first_label = result; } - // concatenation - // pred_new1 points to the last element of the new list - if ( pred_new1 ) + else if (!f_sorter && p_first_added_label && p_first_label) { - pred_new1->set_next( p_first_label ); + // concatenate without sorting; first new, then old + Label* last = p_first_added_label; + while (last->next()) + last = last->next(); + last->set_next(p_first_label); p_first_label = p_first_added_label; } - p_first_added_label = NULL; + else + { + if (p_first_added_label) + p_first_label = p_first_added_label; + } + p_first_added_label = nullptr; // those labels to delete return ret_labels_to_del; } + +#ifdef SPPRC_CHECK_PATH +template<class Label, class StatManager> +inline void c_Dominance_Manager<Label, StatManager>::CheckDominance(Label * label1, Label * label2) +{ + if (label2->b_check_required) + { + cout << "### Label Id=" << label1->Id() << " eliminates Label Id=" << label2->Id() << "\n"; + } +} +#endif + }; -#endif // ESPPTW_DOMINANCE_MGNT_H \ No newline at end of file +#endif // ESPPRC_DOMINANCE_MGNT_H \ No newline at end of file diff --git a/espprc/label.h b/espprc/label.h index d0ab6665ff7888532708874ca40d694ffc8c5240..7a586e5e417ec26aadc4b79be929e87a3b4060b6 100644 --- a/espprc/label.h +++ b/espprc/label.h @@ -4,7 +4,7 @@ #include "ref.h" //////////////////////////////////////////////////////////////////////////////////////////////////////// -//////c_Label +// c_Label //////////////////////////////////////////////////////////////////////////////////////////////////////// namespace espprc { @@ -12,7 +12,7 @@ namespace espprc template <class ResVect, class REF> class c_Label : public ResVect { public: - typedef typename c_Label<ResVect,REF> tLabel; + typedef c_Label<ResVect,REF> tLabel; protected: // the predecessor label in the partial path const c_Label* p_pred; @@ -21,30 +21,35 @@ protected: // the next label of this node for singly-linked list, e.g., used in dominance algorithm c_Label<ResVect,REF>* p_next; int i_id; - bool b_isExtended; // important for instances with arcs with time 0; if bool is set, label can not be deleted in case of dominance which ensures that all labels in improving columns have their predecessor public: c_Label( int id, ResVect&& res_vector, const tLabel* pred, const REF* ref ); - virtual ~c_Label() {}; + // TODO: do we really need a virtual destructor? + virtual ~c_Label() {} // getter const tLabel* predecessor() const { return p_pred; } const REF* generator_REF() const { return p_REF; } - tLabel* next() { return p_next; } // use this to iterate over singly-linked lists + tLabel* next() const { return p_next; } // use this to iterate over singly-linked lists int Id() const { return i_id; } - bool isExtended() { return b_isExtended;} + constexpr bool is_extended() const { return false; } // setter + void set_extended() {} void set_next( c_Label* label ) { p_next = label; } - void setIsExtended() {b_isExtended = true;} +#ifdef SPPRC_CHECK_PATH + bool b_check_required; +#endif }; +//////////////////////////////////////////////////////////////////////////////////////////////////////// +// implementation +//////////////////////////////////////////////////////////////////////////////////////////////////////// template <class ResVect, class REF> c_Label<ResVect,REF>::c_Label( int id, ResVect&& res_vector, const tLabel* pred, const REF* ref) -: i_id(id), +: ResVect(std::move(res_vector)), p_pred(pred), p_REF(ref), - ResVect( std::move(res_vector) ), p_next(NULL), - b_isExtended(false) + i_id(id) {} } diff --git a/espprc/ref.h b/espprc/ref.h index 563b246c65cee174b697802edfd3056c87038701..947761d3339538c0b448e6eda027b6ad025db63e 100644 --- a/espprc/ref.h +++ b/espprc/ref.h @@ -5,7 +5,7 @@ #include <bitset> //////////////////////////////////////////////////////////////////////////////////////////////////////// -//////c_REF +// c_REF //////////////////////////////////////////////////////////////////////////////////////////////////////// namespace espprc { @@ -15,11 +15,11 @@ namespace espprc /* However, sometime they have different components. */ /* - Make sure that only negative rdc labels are created at the sink */ -template <class ResVectFW, class ResVectBW> +template <class ResVectFw, class ResVectBw> class c_REF { public: - typedef typename ResVectFW ResVectFW; - typedef typename ResVectBW ResVectBW; + typedef ResVectFw ResVectFW; + typedef ResVectBw ResVectBW; protected: int i_tail; int i_head; @@ -33,9 +33,12 @@ public: // bool PropagateBw( const ResVectBW& old_res, ResVectBW& new_res ) const; }; +//////////////////////////////////////////////////////////////////////////////////////////////////////// +// implementation +//////////////////////////////////////////////////////////////////////////////////////////////////////// -template <class ResVectFW, class ResVectBW> -c_REF<ResVectFW,ResVectBW>::c_REF(int tail_id, int head_id) +template <class ResVectFw, class ResVectBw> +c_REF<ResVectFw,ResVectBw>::c_REF(int tail_id, int head_id) : i_tail(tail_id), i_head(head_id) {} diff --git a/espprc/solver.h b/espprc/solver.h index 8e7b70a8e94d8884dc55fa57990608dd83826d23..af86224df922f25844b980871bd9f28a376c3fb7 100644 --- a/espprc/solver.h +++ b/espprc/solver.h @@ -1,1160 +1,1659 @@ -#ifndef ESPPRC_SOLVER_H +#ifndef ESPPRC_SOLVER_H #define ESPPRC_SOLVER_H +#include "statistics_mgnt.h" + #include <vector> #include <functional> +#include <algorithm> +#include <iostream> -#include "../Graphml/graphml.h" -#include "../SharedFiles/timeinfo.h" -#include "../SharedFiles/output_formatter.h" - -#define DebugAnka +#include "../graphml/graphml.h" //////////////////////////////////////////////////////////////////////////////////////////////////////// -//////c_Solver +// c_Solver //////////////////////////////////////////////////////////////////////////////////////////////////////// + namespace espprc { - using namespace std; - - template <class REF, class BManagerFW, class DManagerFW, class BManagerBW, class DManagerBW, class MManager> - class c_SPPRC_Solver { - protected: - typedef typename REF::ResVectFW ResVectFW; - typedef typename REF::ResVectBW ResVectBW; - typedef typename BManagerFW::tLabel t_labelFW; - typedef typename BManagerBW::tLabel t_labelBW; - std::vector<std::vector<REF*> > v_fw_star; - std::vector<std::vector<REF*> > v_bw_star; - BManagerFW o_bucket_manager_fw; - std::vector<DManagerFW> v_dominance_manager_fw; - BManagerBW o_bucket_manager_bw; - std::vector<DManagerBW> v_dominance_manager_bw; - MManager* p_merge_manager; - virtual void apply_dominance_FW( int node ); - void apply_dominance_FW(); - virtual void apply_dominance_BW( int node ); - void apply_dominance_BW(); - int i_extended_fw; - int i_extended_bw; - int i_hw; - int i_gen_paths; - - vector<bool> v_domNodes_FW; - //vector<bool> v_domNodes_BW; - -#ifdef DebugAnka - //For Debugging only: - virtual void apply_dominance_FW_TakeCare( int node, int idToPayAttentionOn ); - void apply_dominance_FW_TakeCare(int idToPayAttentionOn); - virtual void apply_dominance_BW_TakeCare( int node, int idToPayAttentionOn ); - void apply_dominance_BW_TakeCare(int idToPayAttentionOn); -#endif - - public: - c_SPPRC_Solver( int max_nodes ); - ~c_SPPRC_Solver(); - - void Add( REF* ref ); - void Add_Fw( REF* ref ); - void Add_Bw( REF* ref ); - void RemoveAllREFs(); - // forward - bool SolveFw( int source, int sink, ResVectFW&& init_res, int maxnumpaths = -1, int maxTime = numeric_limits<int>::max() ); - bool GetPathsFW( const int node, std::vector<t_labelFW*>& paths, std::function<bool (t_labelFW*,t_labelFW*)>* pointer_sorter = nullptr, int max_num_paths = -1 ); - void ClearFW(); - // backward - bool SolveBw( int source, int sink, ResVectBW&& init_res, int maxnumpaths = -1, int maxTime = numeric_limits<int>::max() ); - bool GetPathsBW( const int node, std::vector<t_labelBW*>& paths, std::function<bool (t_labelBW*,t_labelBW*)>* pointer_sorter = nullptr, int maxnumpaths = -1 ); - void ClearBW(); - // bi-directional - bool SolveBidir( MManager& merger, int source, int sink, ResVectFW&& init_res_FW, ResVectBW&& init_res_bw, int maxnumpaths = -1, int maxTime = numeric_limits<int>::max() ); - bool SolveBidir_DynamicHalfway( MManager& merger, int source, int sink, ResVectFW&& init_res_FW, ResVectBW&& init_res_bw, int maxnumpaths = -1, int maxTime = numeric_limits<int>::max() ); - bool GetPathsBidir( const int sink, std::vector<std::pair<double, std::pair<t_labelFW*,t_labelBW*> > >& paths, std::function<bool (std::pair<double,std::pair<t_labelFW*,t_labelBW*> >, std::pair<double,std::pair<t_labelFW*,t_labelBW*> > )>* pointer_sorter = nullptr, int maxnumpaths = -1 ); - //double InfoTimeMerging(){ return d_mergeSeconds; } - // IO - void OutputInStream( std::ostream& s ) const; // output all labels grouped by node - void OutputGraphML(const char* filename); - // statistics - void ResetStatistics(); - c_TimeInfo o_timer_fw_labeling; - c_TimeInfo o_timer_bw_labeling; - c_TimeInfo o_timer_bidir_labeling_fw_part; - c_TimeInfo o_timer_bidir_labeling_bw_part; - c_TimeInfo o_timer_bidir_labeling_merge; - c_TimeInfo o_timer_dyn_bidir_labeling; - int InfoExtendedFW(){ return i_extended_fw; } //counter is reseted in clearFW - int InfoExtendedBW(){ return i_extended_bw; } // counter is reseted in clearBW - int InfoAddedFW(){ return o_bucket_manager_fw.AddedLabels(); } - int InfoAddedBW(){ return o_bucket_manager_bw.AddedLabels(); } - int InfoHw(){ return i_hw; } - - - void writeInfo(int iteration, std::string solver_info, std::string filename, bool dynamic); - void ResetStaticHWP(){ p_merge_manager->ResetStaticHWP(); } // When dynamic and static labeling run together, the HWP has to be reseted before starting the static version - - //void writePricingNetwork(int iteration, string instanceName, string filename); //writes forward and backward star inclusive all information of REF not accessed by instance to txt-file - //void readPricingNetwork(string filename); //reads forward and backward stars - - //void setDominanceNodes(bitset<300> domNodes){bs_domNodes = domNodes;} - void setDominanceNodes_FW(vector<bool>& domNodes){v_domNodes_FW = domNodes;} - //void setDominanceNodes_BW(vector<bool>& domNodes){v_domNodes_BW = domNodes;} -#ifdef DebugAnka - void SolveFw( int source, int sink, ResVectFW&& init_res, const vector<int>& expectedTour, int maxnumpaths = -1 ); //fw-label needs method: bool containsRoute(const vector<int>& route, int& nextExpectedNode) const; - //void SolveBw( int source, int sink, ResVectBW&& init_res, const vector<int>& expectedTour, int maxnumpaths = -1 ); //bw-label needs method: bool containsRoute(const vector<int>& route, int& nextExpectedNode) const; - //void SolveBidir( MManager& merger, int source, int sink, ResVectFW&& init_res_FW, ResVectBW&& init_res_bw, const vector<int>& expectedTour, int maxnumpaths = -1 ); //fw- and bw-label need method containsRoute - void SolveBidir_DynamicHalfway( MManager& merger, int source, int sink, ResVectFW&& init_res_FW, ResVectBW&& init_res_bw, const vector<int>& expectedTour, int maxnumpaths = -1 ); +using namespace std; + + +template <class REF, class ExtManagerFW, class DManagerFW, class ExtManagerBW, class DManagerBW, + class MManager, class StatManager = c_EmptyStatisticsManager> +class c_SPPRC_Solver { +protected: + typedef typename REF::ResVectFW ResVectFW; + typedef typename REF::ResVectBW ResVectBW; + typedef typename ExtManagerFW::tLabel t_labelFW; + typedef typename ExtManagerBW::tLabel t_labelBW; + double d_EPS; + vector<vector<REF*> > v_fw_star; + vector<vector<REF*> > v_bw_star; + ExtManagerFW o_extension_manager_fw; + vector<DManagerFW> v_dominance_manager_fw; + ExtManagerBW o_extension_manager_bw; + vector<DManagerBW> v_dominance_manager_bw; + MManager* p_merge_manager; + void apply_dominance_FW( int node ); + void apply_dominance_FW(); + void apply_dominance_BW( int node ); + void apply_dominance_BW(); + void apply_final_dominance_FW(int node); + void apply_final_dominance_FW(); + void apply_final_dominance_BW(int node); + void apply_final_dominance_BW(); + int i_extended_fw; + int i_extended_bw; + int i_hw; + int i_gen_paths; + int i_id_fwd; + int i_id_bwd; + StatManager o_initial_stat; + StatManager* p_stat; +public: + c_SPPRC_Solver( int max_nodes ); + ~c_SPPRC_Solver(); + + void Add( REF* ref ); + void Add_Fw( REF* ref ); + void Add_Bw( REF* ref ); + void RemoveAllREFs(); + void SetEPS( double eps ) { d_EPS = eps; } + // forward + bool SolveFw( int source, int sink, ResVectFW&& init_res, int max_num_paths = numeric_limits<int>::max(), int maxTime = numeric_limits<int>::max() ); + bool GetPathsFW( const int node, vector<t_labelFW*>& paths, function<bool (t_labelFW*,t_labelFW*)>* pointer_sorter = nullptr, int max_num_paths = numeric_limits<int>::max() ); + void ClearFW(); + bool WarmstartSolveFw(int source, int sink, int max_num_paths = numeric_limits<int>::max(), int maxTime = numeric_limits<int>::max()); + DManagerFW& DominanceManagerFW(int i) { return v_dominance_manager_fw[i]; } + std::vector<DManagerFW>& GetLabelsFW() { return v_dominance_manager_fw; } + // backward + bool SolveBw( int source, int sink, ResVectBW&& init_res, int max_num_paths = numeric_limits<int>::max(), int maxTime = numeric_limits<int>::max() ); + bool GetPathsBW(const int node, vector<t_labelBW*>& paths, function<bool(t_labelBW*, t_labelBW*)>* pointer_sorter = nullptr, int max_num_paths = numeric_limits<int>::max()); + void ClearBW(); + bool WarmstartSolveBw(int source, int sink, int max_num_paths = numeric_limits<int>::max(), int maxTime = numeric_limits<int>::max()); + DManagerBW& DominanceManagerBW(int i) { return v_dominance_manager_bw[i]; } + std::vector<DManagerBW>& GetLabelsBW() { return v_dominance_manager_bw; } + // bi-directional + bool SolveBidir( MManager& merger, int source, int sink, ResVectFW&& init_res_FW, ResVectBW&& init_res_bw, int max_num_paths = numeric_limits<int>::max(), int maxTime = numeric_limits<int>::max() ); + bool SolveBidir_DynamicHalfway( MManager& merger, int source, int sink, ResVectFW&& init_res_FW, ResVectBW&& init_res_bw, int max_num_paths = numeric_limits<int>::max(), int maxTime = numeric_limits<int>::max() ); + bool GetPathsBidir(const int sink, vector<pair<double, pair<t_labelFW*, t_labelBW*> > >& paths, function<bool(pair<double, pair<t_labelFW*, t_labelBW*> >, pair<double, pair<t_labelFW*, t_labelBW*> >)>* pointer_sorter = nullptr, int max_num_paths = numeric_limits<int>::max()); + bool GetPathsBidirBuckets(const int sink, vector<pair<double, pair<t_labelFW*, t_labelBW*> > >& paths, function<bool(pair<double, pair<t_labelFW*, t_labelBW*> >, pair<double, pair<t_labelFW*, t_labelBW*> >)>* pointer_sorter = nullptr, int max_num_paths = numeric_limits<int>::max()); + const MManager* MergeManager() const { return p_merge_manager; } + StatManager& StatisticsManager() { return *p_stat; } + /* this can be useful to have e.g. different statistics per network size */ + void SetStatisticsManager(StatManager& stat); + // bi-directional for symmetric ESPPRCs + // Pay attention: GetPathsBidir_Symmetric may return source-source-paths as well as source-sink-paths + bool SolveBidir_Symmetric( MManager& merger, int source, int sink, ResVectFW&& init_res, int max_num_paths = numeric_limits<int>::max(), int maxTime = numeric_limits<int>::max() ); + bool GetPathsBidir_Symmetric(const int sink, vector<pair<double, pair<t_labelFW*, t_labelBW*> > >& paths, function<bool(t_labelFW*, t_labelBW*)>* pointer_sorter_merge = nullptr, function<bool(pair<double, pair<t_labelFW*, t_labelBW*> >, pair<double, pair<t_labelFW*, t_labelBW*> >)>* pointer_sorter = nullptr, int max_num_paths = numeric_limits<int>::max()); + bool GetPathsBidirBuckets_Symmetric(const int sink, vector<pair<double, pair<t_labelFW*, t_labelBW*> > >& paths, function<bool(t_labelFW*, t_labelBW*)>* pointer_sorter_merge = nullptr, function<bool(pair<double, pair<t_labelFW*, t_labelBW*> >, pair<double, pair<t_labelFW*, t_labelBW*> >)>* pointer_sorter = nullptr, int max_num_paths = numeric_limits<int>::max()); + // IO + void OutputInStream( ostream& s ) const; // output all labels grouped by node + void OutputGraphML( string filename ); + int InfoExtendedFW() const { return i_extended_fw; } // counter is reset in clearFW + int InfoExtendedBW() const { return i_extended_bw; } // counter is reset in clearBW + int InfoAddedFW() const { return o_extension_manager_fw.AddedLabels(); } + int InfoAddedBW() const { return o_extension_manager_bw.AddedLabels(); } + int InfoHw() const { return i_hw; } + // The following section is for debug purposes +#ifdef SPPRC_CHECK_PATH + // Find out why a given path is missing, because + // (1) it is (incorrectly?) dominated, (2) or it is not generated, (3) or it is not found in the merge procedure +private: + bool b_check_path; + bool b_check_verbose; + vector<REF*> v_path_to_check; + bool CheckNewLabelFW(t_labelFW* label); + bool CheckNewLabelBW(t_labelBW* label); +public: + bool CheckPath(const vector<REF*>& path, bool verbose); #endif - }; - - - - //template <class REF, class BManagerFW, class DManagerFW, class BManagerBW, class DManagerBW, class MManager> - //void espprc::c_SPPRC_Solver<REF, BManagerFW, DManagerFW, BManagerBW, DManagerBW, MManager>::writePricingNetwork(int iteration, string instanceName, string filename) - //{ - // std::stringstream ss; - // ss << filename << "_" << instanceName << "_" << iteration << ".txt"; - // std::string name = ss.str(); - // ofstream file(name); - - // file << "Instance " << instanceName << " Iteration " << iteration << endl; - - // file << "n " << v_fw_star.size() << endl; - - // //Write forward star - // int n = (int) v_fw_star.size(); - // for ( int i = 0; i < n; i++){ - // file << "FW_STAR " << i << endl; - // for each( REF* ref in v_fw_star[i]){ - // ref->OutputInStream(file); - // } - // file << endl; - // } - // file << "END" << endl; - - // //Write backward star - // n = (int) v_bw_star.size(); - // for ( int i = 0; i < n; i++){ - // file << "BW_STAR " << i << endl; - // for each( REF* ref in v_bw_star[i]){ - // ref->OutputInStream(file); - // } - // file << endl; - // } - // file << "END" << endl; - - // //Write all info of Instance_With_RDC (NG, SubsetRow, numBadArcs, RDC) - // v_fw_star[0].back()->OutputInstanceInfoInStream(file); - //} - - //template <class REF, class BManagerFW, class DManagerFW, class BManagerBW, class DManagerBW, class MManager> - //void espprc::c_SPPRC_Solver<REF, BManagerFW, DManagerFW, BManagerBW, DManagerBW, MManager>::readPricingNetwork(string filename) - //{ - // ifstream file(filename, ios_base::in); - // char buffer[1023]; - // file.getline( buffer, 1023 ); //Instance Iteration - // file.getline( buffer, 1023 ); //Num Nodes - // std::istringstream line( buffer ); - // string token; - // line >> token; - // if ( token != "n" ){ - // throw; - // } - // int n; - // line >> n; - // v_fw_star = vector<vector<REF*> >(n); - // v_bw_star = vector<vector<REF*> >(n); - // file.getline( buffer, 1023 ); - // line( buffer ); - // line >> token; - // while ( token != "END" ){ - // int i; - // if ( token == "FW_STAR" ){ - // line >> i; - // } else { - // throw; - // //v_fw_star[i].push_back( new REF( line ) ); //TODO - // } - - // file.getline( buffer, 1023 ); - // std::istringstream line( buffer ); - // line >> token; - // } - //} - - template <class REF, class BManagerFW, class DManagerFW, class BManagerBW, class DManagerBW, class MManager> - void espprc::c_SPPRC_Solver<REF, BManagerFW, DManagerFW, BManagerBW, DManagerBW, MManager>::writeInfo(int iteration, std::string solver_info, std::string filename,bool dynamic) - { - using namespace formatted_output; - //instance +}; - c_HostnameField host(100, "Computer"); - if (dynamic) - { - //mergetime and generated cols is missing - c_IntegerField Iter(1, "Iteration", iteration); - c_StringField Solver_info(2, "Solver_Info", solver_info); +//////////////////////////////////////////////////////////////////////////////////////////////////////// +// implementation +//////////////////////////////////////////////////////////////////////////////////////////////////////// - c_IntegerField gen_paths(11, "gen.paths|dynamic", i_gen_paths); - c_IntegerField halfwaypoint_dynamic(12, "HWP|dynamic", i_hw); - c_IntegerField AddedFW_dynamic(13, "FW|Added|dynamic", InfoAddedFW()); - c_IntegerField AddedBW_dynamic(14, "BW|Added|dynamic", InfoAddedBW()); - c_IntegerField Addedsum_dynamic(15, "sum|Added|dynamic", InfoAddedFW() + InfoAddedBW()); - c_IntegerField ExtendedFW_dynamic(16, "FW|Extended|dynamic", InfoExtendedFW()); - c_IntegerField ExtendedBW_dynamic(17, "BW|Extended|dynamic", InfoExtendedBW()); - c_IntegerField Extendedsum_dynamic(18, "sum|Extended|dynamic", InfoExtendedFW() + InfoExtendedBW()); - c_DoubleField dyn_mergetime(19, "mergetime|dynamic", max(0.001, o_timer_bidir_labeling_merge.Seconds())); - c_DoubleField dyn_solvetime_real(20, "real|solvetime|dynamic", max(0.001, o_timer_dyn_bidir_labeling.Seconds())); +template <class REF, class ExtManagerFW, class DManagerFW, class ExtManagerBW, class DManagerBW, class MManager, class StatManager> +c_SPPRC_Solver<REF, ExtManagerFW, DManagerFW, ExtManagerBW, DManagerBW, MManager, StatManager> + ::c_SPPRC_Solver(int max_nodes) +: d_EPS( 0.00001 ), + v_fw_star(max_nodes), + v_bw_star(max_nodes), + v_dominance_manager_fw(max_nodes), + v_dominance_manager_bw(max_nodes), + p_merge_manager(nullptr), + i_extended_fw(0), + i_extended_bw(0), + o_initial_stat(), + p_stat(&o_initial_stat) +#ifdef SPPRC_CHECK_PATH + ,b_check_path(false), + b_check_verbose(false) +#endif +{ + p_stat->resize(max_nodes); + int i = 0; + for (auto&& dm : v_dominance_manager_fw) + { + dm.SetInfo(true, i++); + dm.SetStatisticsManager(*p_stat); + } + i = 0; + for (auto&& dm : v_dominance_manager_bw) + { + dm.SetInfo(false, i++); + dm.SetStatisticsManager(*p_stat); + } +} - host.OutputToFile(filename); - } - else - { - c_IntegerField Iter(1, "Iteration", iteration); - c_StringField Solver_info(2, "Solver_Info", solver_info); - //static - c_IntegerField gen_paths(11, "gen.paths|static", i_gen_paths); - c_IntegerField halfwaypoint_static(12, "HWP|static", i_hw); - c_IntegerField AddedFW_static(13, "FW|Added|static", InfoAddedFW()); - c_IntegerField AddedBW_static(14, "BW|Added|static", InfoAddedBW()); - c_IntegerField Addedsum_static(15, "sum|Added|static", InfoAddedFW() + InfoAddedBW()); - c_IntegerField ExtendedFW_static(16, "FW|Extended|static", InfoExtendedFW()); - c_IntegerField ExtendedBW_static(17, "BW|Extended|static", max(1,InfoExtendedBW())); - c_IntegerField Extended_sum_static(18, "sum|Added|static", InfoExtendedFW() + InfoExtendedBW()); - c_DoubleField stat_mergetime(19, "mergetime|static", max(0.001, o_timer_bidir_labeling_merge.Seconds())); - c_DoubleField stat_solvetime_sum_real(20, "sum real|solvetime|static", max(0.001, o_timer_bidir_labeling_fw_part.Seconds() + o_timer_bidir_labeling_bw_part.Seconds())); - - c_DoubleField stat_solvetime_fw(22, "FW|solvetime|static", max(0.001, o_timer_bidir_labeling_fw_part.Seconds())); - c_DoubleField stat_solvetime_bw(23, "BW|solvetime|static", max(0.001, o_timer_bidir_labeling_bw_part.Seconds())); - host.OutputToFile(filename); +template <class REF, class ExtManagerFW, class DManagerFW, class ExtManagerBW, class DManagerBW, class MManager, class StatManager> +void c_SPPRC_Solver<REF, ExtManagerFW, DManagerFW, ExtManagerBW, DManagerBW, MManager, StatManager>::SetStatisticsManager(StatManager& stat) +{ + p_stat = &stat; + p_stat->resize((int)v_fw_star.size()); + for (auto&& dm : v_dominance_manager_fw) + dm.SetStatisticsManager(stat); + for (auto&& dm : v_dominance_manager_bw) + dm.SetStatisticsManager(stat); +} - } +template <class REF, class ExtManagerFW, class DManagerFW, class ExtManagerBW, class DManagerBW, class MManager, class StatManager> +c_SPPRC_Solver<REF, ExtManagerFW, DManagerFW, ExtManagerBW, DManagerBW, MManager, StatManager>::~c_SPPRC_Solver() +{ + ClearFW(); + ClearBW(); +} - } - template <class REF, class BManagerFW, class DManagerFW, class BManagerBW, class DManagerBW, class MManager> - void espprc::c_SPPRC_Solver<REF, BManagerFW, DManagerFW, BManagerBW, DManagerBW, MManager>::RemoveAllREFs() - { - for( int i = 0; i < (int)v_fw_star.size(); i++){ - v_fw_star[i].clear(); - v_bw_star[i].clear(); - } - } +template <class REF, class ExtManagerFW, class DManagerFW, class ExtManagerBW, class DManagerBW, class MManager, class StatManager> +void c_SPPRC_Solver<REF, ExtManagerFW, DManagerFW, ExtManagerBW, DManagerBW, MManager, StatManager> + ::Add( REF* ref ) +{ + v_fw_star[ref->Tail()].push_back(ref); + v_bw_star[ref->Head()].push_back(ref); +} - // general implementation +template <class REF, class ExtManagerFW, class DManagerFW, class ExtManagerBW, class DManagerBW, class MManager, class StatManager> +void c_SPPRC_Solver<REF, ExtManagerFW, DManagerFW, ExtManagerBW, DManagerBW, MManager, StatManager>::Add_Fw( REF* ref ) +{ + v_fw_star[ref->Tail()].push_back(ref); +} - template <class REF, class BManagerFW, class DManagerFW, class BManagerBW, class DManagerBW, class MManager> - c_SPPRC_Solver<REF, BManagerFW, DManagerFW, BManagerBW, DManagerBW, MManager> - ::c_SPPRC_Solver( int max_nodes ) - : v_fw_star(max_nodes), - v_bw_star(max_nodes), - v_dominance_manager_fw(max_nodes), - v_dominance_manager_bw(max_nodes), - p_merge_manager( nullptr ), - i_extended_fw(0), - i_extended_bw(0) - {} + +template <class REF, class ExtManagerFW, class DManagerFW, class ExtManagerBW, class DManagerBW, class MManager, class StatManager> +void c_SPPRC_Solver<REF, ExtManagerFW, DManagerFW, ExtManagerBW, DManagerBW, MManager, StatManager>::Add_Bw( REF* ref ) +{ + v_bw_star[ref->Head()].push_back(ref); +} - template <class REF, class BManagerFW, class DManagerFW, class BManagerBW, class DManagerBW, class MManager> - c_SPPRC_Solver<REF, BManagerFW, DManagerFW, BManagerBW, DManagerBW, MManager>::~c_SPPRC_Solver() +template <class REF, class ExtManagerFW, class DManagerFW, class ExtManagerBW, class DManagerBW, class MManager, class StatManager> +void c_SPPRC_Solver<REF, ExtManagerFW, DManagerFW, ExtManagerBW, DManagerBW, MManager, StatManager> + ::RemoveAllREFs() +{ + for( int i = 0; i < (int)v_fw_star.size(); i++) { - ClearFW(); - ClearBW(); + v_fw_star[i].clear(); + v_bw_star[i].clear(); } +} +// forward labeling - template <class REF, class BManagerFW, class DManagerFW, class BManagerBW, class DManagerBW, class MManager> - void c_SPPRC_Solver<REF, BManagerFW, DManagerFW, BManagerBW, DManagerBW, MManager> - ::Add( REF* ref ) - { - v_fw_star[ref->Tail()].push_back(ref); - v_bw_star[ref->Head()].push_back(ref); - } +template <class REF, class ExtManagerFW, class DManagerFW, class ExtManagerBW, class DManagerBW, class MManager, class StatManager> +void c_SPPRC_Solver<REF, ExtManagerFW, DManagerFW, ExtManagerBW, DManagerBW, MManager, StatManager> + ::ClearFW() +{ + o_extension_manager_fw.clear(); + int dom_size=(int) v_dominance_manager_fw.size(); + for (int i=0;i< dom_size;i++) + v_dominance_manager_fw[i].clear(); + i_extended_fw = 0; + i_hw = -1; + i_gen_paths = -1; +} - template <class REF, class BManagerFW, class DManagerFW, class BManagerBW, class DManagerBW, class MManager> - void espprc::c_SPPRC_Solver<REF, BManagerFW, DManagerFW, BManagerBW, DManagerBW, MManager>::Add_Fw( REF* ref ) - { - v_fw_star[ref->Tail()].push_back(ref); - } - template <class REF, class BManagerFW, class DManagerFW, class BManagerBW, class DManagerBW, class MManager> - void espprc::c_SPPRC_Solver<REF, BManagerFW, DManagerFW, BManagerBW, DManagerBW, MManager>::Add_Bw( REF* ref ) +template <class REF, class ExtManagerFW, class DManagerFW, class ExtManagerBW, class DManagerBW, class MManager, class StatManager> +bool c_SPPRC_Solver<REF, ExtManagerFW, DManagerFW, ExtManagerBW, DManagerBW, MManager, StatManager> + ::SolveFw( int source, int sink, ResVectFW&& init_res, int max_num_paths, int maxTime ) +{ + c_Stopwatch timer; + timer.Start(); + p_stat->OnStartFwLabeling(); + ClearFW(); + i_id_fwd = 0; + t_labelFW* p_label = new t_labelFW(i_id_fwd++, std::move(init_res), nullptr, nullptr); +#ifdef SPPRC_CHECK_PATH + if (b_check_path) + CheckNewLabelFW(p_label); +#endif + o_extension_manager_fw.insert( p_label ); + v_dominance_manager_fw[source].insert( p_label ); + // iterate over the labels + ResVectFW new_res; + while (( p_label = o_extension_manager_fw.get_next() )) { - v_bw_star[ref->Head()].push_back(ref); + int id = p_label->Id(); + // dominance can be delayed to any point in time, the extension manager decides when + if (o_extension_manager_fw.invoke_dominance_algorithm()) + { + p_stat->OnStartFwDominance(); + apply_dominance_FW(); + p_stat->OnEndFwDominance(); + if (v_dominance_manager_fw[sink].size() >= max_num_paths) + { + p_stat->OnStartFwDominance(); + apply_final_dominance_FW(); + p_stat->OnEndFwDominance(); + p_stat->OnEndFwLabeling(); + return false; + } + } + // has p_label been deleted? + if (o_extension_manager_fw.is_erased(id)) + continue; + // extension... + i_extended_fw++; + const ResVectFW& curr_res( *p_label ); + int node = ( p_label->generator_REF() ? p_label->generator_REF()->Head() : source ); + // iterate over forward star of the node + p_stat->OnStartFwPropagate(); + int max_idx = (int)v_fw_star[node].size(); + for ( int idx=0; idx<max_idx; idx++ ) + { + REF* p_ref = v_fw_star[node][idx]; + if ( p_ref->PropagateFw( curr_res, new_res ) ) + { + p_label->set_extended(); + t_labelFW* new_label = new t_labelFW(i_id_fwd++, std::move(new_res), p_label, p_ref); +#ifdef SPPRC_CHECK_PATH + if(b_check_path) + CheckNewLabelFW(new_label); +#endif + o_extension_manager_fw.insert( new_label ); + int new_node = p_ref->Head(); + v_dominance_manager_fw[new_node].insert( new_label ); + } + } + p_stat->OnEndFwPropagate(); + //check global time + if (timer.Seconds() > maxTime) + { + p_stat->OnEndFwLabeling(); + ClearFW(); + return false; + } } + // final dominance + p_stat->OnStartFwDominance(); + apply_final_dominance_FW(); + p_stat->OnEndFwDominance(); + p_stat->OnEndFwLabeling(); + return ( v_dominance_manager_fw[sink].size() < max_num_paths ); +} - // forward labeling - template <class REF, class BManagerFW, class DManagerFW, class BManagerBW, class DManagerBW, class MManager> - void c_SPPRC_Solver<REF, BManagerFW, DManagerFW, BManagerBW, DManagerBW, MManager> - ::ClearFW() +template <class REF, class ExtManagerFW, class DManagerFW, class ExtManagerBW, class DManagerBW, class MManager, class StatManager> +bool c_SPPRC_Solver<REF, ExtManagerFW, DManagerFW, ExtManagerBW, DManagerBW, MManager, StatManager> +::WarmstartSolveFw(int source, int sink, int max_num_paths, int maxTime) +{ + c_Stopwatch timer; + timer.Start(); + p_stat->OnStartFwLabeling(); + int n = (int)v_dominance_manager_fw.size(); + if (!p_merge_manager) { - o_bucket_manager_fw.clear(); - int dom_size=(int) v_dominance_manager_fw.size(); - for (int i=0;i< dom_size;i++) - v_dominance_manager_fw[i].clear(); - i_extended_fw = 0; - i_hw = -1; - i_gen_paths = -1; + cout << "Run SolveBidir(...) first. " << endl; + throw; } - - - template <class REF, class BManagerFW, class DManagerFW, class BManagerBW, class DManagerBW, class MManager> - bool c_SPPRC_Solver<REF, BManagerFW, DManagerFW, BManagerBW, DManagerBW, MManager> - ::SolveFw( int source, int sink, ResVectFW&& init_res, int maxnumpaths, int maxTime ) + for (int i = 0; i < n; i++) + for (t_labelFW* label_fw = v_dominance_manager_fw[i].begin(); label_fw; label_fw = v_dominance_manager_fw[i].next(label_fw)) + if (!p_merge_manager->BeforeHalfWayPointFW(*label_fw)) + o_extension_manager_fw.insert(label_fw); + o_extension_manager_fw.ResetBucketIndex(); + o_extension_manager_fw.IncreaseBucketIndex(); + for (int i = 0; i < n; i++) + v_dominance_manager_fw[i].PrepareForWarmstart(o_extension_manager_fw.GetBucketIndex()); + + t_labelFW* p_label = nullptr; + // iterate over the labels + ResVectFW new_res; + while ((p_label = o_extension_manager_fw.get_next())) { - bool solvedOptimal = true; - c_TimeInfo timer; - timer.Start(); - o_timer_fw_labeling.Start(); - ClearFW(); - int id = 0; - t_labelFW* p_label = new t_labelFW( id++, std::move(init_res), NULL, NULL ); - o_bucket_manager_fw.insert( p_label ); - v_dominance_manager_fw[source].insert( p_label ); - // iterate over the labels - ResVectFW new_res; - while ( (p_label = o_bucket_manager_fw.get_next()) && (v_dominance_manager_fw[sink].size()<maxnumpaths ) ) - { - i_extended_fw++; - //check global time - if( timer.Seconds() > maxTime ) + int id = p_label->Id(); + // dominance can be delayed to any point in time, the bucket manager decides when + if (o_extension_manager_fw.invoke_dominance_algorithm()) + { + p_stat->OnStartFwDominance(); + apply_dominance_FW(); + p_stat->OnEndFwDominance(); + if (v_dominance_manager_fw[sink].size() >= max_num_paths) { - timer.Stop(); - o_timer_fw_labeling.Stop(); - ClearFW(); - return false; + p_stat->OnStartFwDominance(); + apply_final_dominance_FW(); + p_stat->OnEndFwDominance(); + p_stat->OnEndFwLabeling(); + return false; } - const ResVectFW& curr_res( *p_label ); - int node = ( p_label->generator_REF() ? p_label->generator_REF()->Head() : source ); - // iterate over forward star of the node - int max_idx = (int)v_fw_star[node].size(); - for ( int idx=0; idx<max_idx; idx++ ) + } + // has p_label been deleted? + if (o_extension_manager_fw.is_erased(id)) + continue; + // extension... + i_extended_fw++; + const ResVectFW& curr_res(*p_label); + int node = (p_label->generator_REF() ? p_label->generator_REF()->Head() : source); + // iterate over forward star of the node + p_stat->OnStartFwPropagate(); + int max_idx = (int)v_fw_star[node].size(); + for (int idx = 0; idx<max_idx; idx++) + { + REF* p_ref = v_fw_star[node][idx]; + if (p_ref->PropagateFw(curr_res, new_res)) { - REF* p_ref = v_fw_star[node][idx]; - if ( p_ref->PropagateFw( curr_res, new_res ) ) - { - - t_labelFW* new_label = new t_labelFW( id++, move(new_res), p_label, p_ref ); - o_bucket_manager_fw.insert( new_label ); - int new_node = p_ref->Head(); - v_dominance_manager_fw[new_node].insert( new_label ); - } + p_label->set_extended(); + t_labelFW* new_label = new t_labelFW(i_id_fwd++, std::move(new_res), p_label, p_ref); +#ifdef SPPRC_CHECK_PATH + if ( b_check_path) + CheckNewLabelFW(new_label); +#endif + o_extension_manager_fw.insert(new_label); + int new_node = p_ref->Head(); + v_dominance_manager_fw[new_node].insert(new_label); } - p_label->setIsExtended(); - // dominance can be delayed to any point in time, the bucket manager decides when - if ( o_bucket_manager_fw.invoke_dominance_algorithm() ) - apply_dominance_FW(); } - if( v_dominance_manager_fw[sink].size() >= maxnumpaths ) - solvedOptimal = false; - // final dominance - apply_dominance_FW(); - o_timer_fw_labeling.Stop(); - return solvedOptimal; + p_stat->OnEndFwPropagate(); + //check global time + if (timer.Seconds() > maxTime) + { + p_stat->OnEndFwLabeling(); + ClearFW(); + return false; + } } + // final dominance + p_stat->OnStartFwDominance(); + apply_final_dominance_FW(); + p_stat->OnEndFwDominance(); + p_stat->OnEndFwLabeling(); + return (v_dominance_manager_fw[sink].size() < max_num_paths); +} - template <class REF, class BManagerFW, class DManagerFW, class BManagerBW, class DManagerBW, class MManager> - void c_SPPRC_Solver<REF, BManagerFW, DManagerFW, BManagerBW, DManagerBW, MManager> - ::apply_dominance_FW( int new_node ) +template <class REF, class ExtManagerFW, class DManagerFW, class ExtManagerBW, class DManagerBW, class MManager, class StatManager> +void c_SPPRC_Solver<REF, ExtManagerFW, DManagerFW, ExtManagerBW, DManagerBW, MManager, StatManager> + ::apply_dominance_FW( int new_node ) +{ + t_labelFW* label_to_delete = v_dominance_manager_fw[new_node].apply_dominance(o_extension_manager_fw.GetBucketIndex()); + while ( label_to_delete ) { - t_labelFW* label_to_delete = v_dominance_manager_fw[new_node].apply_dominance(); - while ( label_to_delete ) + if (!label_to_delete->is_extended()) { - o_bucket_manager_fw.erase( label_to_delete ); + o_extension_manager_fw.erase(label_to_delete); t_labelFW* next_label = label_to_delete->next(); - if( label_to_delete->isExtended() ){ - o_bucket_manager_fw.insertLabelStoredSinceExtended(label_to_delete); - } else{ - delete label_to_delete; - } + delete label_to_delete; label_to_delete = next_label; - - /*o_bucket_manager_fw.erase( label_to_delete ); + } + else + { + //TODO: Collect Labels for later deleting t_labelFW* next_label = label_to_delete->next(); - delete label_to_delete; - label_to_delete = next_label;*/ + label_to_delete = next_label; } } +} + +template <class REF, class ExtManagerFW, class DManagerFW, class ExtManagerBW, class DManagerBW, class MManager, class StatManager> +void c_SPPRC_Solver<REF, ExtManagerFW, DManagerFW, ExtManagerBW, DManagerBW, MManager, StatManager> + ::apply_dominance_FW() +{ + int max_idx=(int)v_dominance_manager_fw.size(); + for ( int i=0; i<max_idx; i++ ) + apply_dominance_FW(i); +} - template <class REF, class BManagerFW, class DManagerFW, class BManagerBW, class DManagerBW, class MManager> - void c_SPPRC_Solver<REF, BManagerFW, DManagerFW, BManagerBW, DManagerBW, MManager> - ::apply_dominance_FW() + +template <class REF, class ExtManagerFW, class DManagerFW, class ExtManagerBW, class DManagerBW, class MManager, class StatManager> +void c_SPPRC_Solver<REF, ExtManagerFW, DManagerFW, ExtManagerBW, DManagerBW, MManager, StatManager> +::apply_final_dominance_FW(int new_node) +{ + t_labelFW* label_to_delete = v_dominance_manager_fw[new_node].apply_final_dominance(o_extension_manager_fw.GetBucketIndex()); + while (label_to_delete) { - int max_idx=(int)v_dominance_manager_fw.size(); - for ( int i=0; i<max_idx; i++ ){ - if( v_domNodes_FW[i] ) - apply_dominance_FW(i); + if (!label_to_delete->is_extended()) + { + o_extension_manager_fw.erase(label_to_delete); + t_labelFW* next_label = label_to_delete->next(); + delete label_to_delete; + label_to_delete = next_label; + } + else + { + //TODO: Collect Labels for later deleting + t_labelFW* next_label = label_to_delete->next(); + label_to_delete = next_label; } } +} + +template <class REF, class ExtManagerFW, class DManagerFW, class ExtManagerBW, class DManagerBW, class MManager, class StatManager> +void c_SPPRC_Solver<REF, ExtManagerFW, DManagerFW, ExtManagerBW, DManagerBW, MManager, StatManager> +::apply_final_dominance_FW() +{ + int max_idx = (int)v_dominance_manager_fw.size(); + for (int i = 0; i<max_idx; i++) + apply_final_dominance_FW(i); +} - template <class REF, class BManagerFW, class DManagerFW, class BManagerBW, class DManagerBW, class MManager> - bool c_SPPRC_Solver<REF, BManagerFW, DManagerFW, BManagerBW, DManagerBW, MManager> - ::GetPathsFW( const int sink, std::vector<t_labelFW*>& Tours, std::function<bool (t_labelFW*,t_labelFW*)>* pointer_sorter, int max_num_paths ) +template <class REF, class ExtManagerFW, class DManagerFW, class ExtManagerBW, class DManagerBW, class MManager, class StatManager> +bool c_SPPRC_Solver<REF, ExtManagerFW, DManagerFW, ExtManagerBW, DManagerBW, MManager, StatManager> + ::GetPathsFW( const int sink, vector<t_labelFW*>& paths, function<bool (t_labelFW*,t_labelFW*)>* pointer_sorter, int max_num_paths ) +{ + // attention: max_nodes must be number of nodes! + t_labelFW* iter = v_dominance_manager_fw[sink].begin(); + while(iter) + { + paths.push_back(iter); + iter=v_dominance_manager_fw[sink].next(iter); + } + if ( (int)paths.size() > max_num_paths ) { - // attention: max_nodes must be number of nodes! - t_labelFW* iter = v_dominance_manager_fw[sink].begin(); - while(iter) + if ( pointer_sorter ) + sort( paths.begin(), paths.end(), *pointer_sorter ); + paths.resize( max_num_paths ); + if (!pointer_sorter) + return false; + } + return true; +} + +// backward + +template <class REF, class ExtManagerFW, class DManagerFW, class ExtManagerBW, class DManagerBW, class MManager, class StatManager> +void c_SPPRC_Solver<REF, ExtManagerFW, DManagerFW, ExtManagerBW, DManagerBW, MManager, StatManager> + ::ClearBW() +{ + o_extension_manager_bw.clear(); + int max_idx=(int) v_dominance_manager_bw.size(); + for (int i=0;i< max_idx;i++) + v_dominance_manager_bw[i].clear(); + i_extended_bw = 0; +} + + +template <class REF, class ExtManagerFW, class DManagerFW, class ExtManagerBW, class DManagerBW, class MManager, class StatManager> +bool c_SPPRC_Solver<REF, ExtManagerFW, DManagerFW, ExtManagerBW, DManagerBW, MManager, StatManager> + ::SolveBw(int source, int sink, ResVectBW&& init_res, int max_num_paths, int maxTime ) +{ + c_Stopwatch timer_Solver; + timer_Solver.Start(); + p_stat->OnStartBwLabeling(); + ClearBW(); + i_id_bwd = 0; + t_labelBW* p_label = new t_labelBW(i_id_bwd++, std::move(init_res), nullptr, nullptr); +#ifdef SPPRC_CHECK_PATH + if (b_check_path) + CheckNewLabelBW(p_label); +#endif + o_extension_manager_bw.insert( p_label ); + v_dominance_manager_bw[sink].insert( p_label ); + // iterate over the labels + ResVectBW new_res; + while ( (p_label = o_extension_manager_bw.get_next() )) + { + int id = p_label->Id(); + // dominance can be delayed to any point in time, the bucket manager decides when + if (o_extension_manager_bw.invoke_dominance_algorithm()) + { + p_stat->OnStartBwDominance(); + apply_dominance_BW(); + p_stat->OnEndBwDominance(); + if (v_dominance_manager_bw[source].size() >= max_num_paths) + { + p_stat->OnStartBwDominance(); + apply_final_dominance_BW(); + p_stat->OnEndBwDominance(); + p_stat->OnStartBwLabeling(); + return false; + } + } + // has p_label been deleted? + if (o_extension_manager_bw.is_erased(id)) + continue; + // entension + i_extended_bw++; + const ResVectBW& curr_res( *p_label ); + int node = ( p_label->generator_REF() ? p_label->generator_REF()->Tail() : sink ); + // iterate over backward star of the node + p_stat->OnStartBwPropagate(); + int max_idx = (int)v_bw_star[node].size(); + for ( int idx=0; idx<max_idx; idx++ ) { - Tours.push_back(iter); - iter=v_dominance_manager_fw[sink].next(); + REF* p_ref = v_bw_star[node][idx]; + if ( p_ref->PropagateBw( curr_res, new_res ) ) + { + p_label->set_extended(); + t_labelBW* new_label = new t_labelBW(i_id_bwd++, std::move(new_res), p_label, p_ref); +#ifdef SPPRC_CHECK_PATH + if (b_check_path) + CheckNewLabelBW(new_label); +#endif + o_extension_manager_bw.insert( new_label ); + int new_node = p_ref->Tail(); + v_dominance_manager_bw[new_node].insert( new_label ); + } } - if ( max_num_paths > 0 && (int)Tours.size() > max_num_paths ) + p_stat->OnEndBwPropagate(); + // check global time + if (timer_Solver.Seconds() > maxTime) { - if ( pointer_sorter ) - sort( Tours.begin(), Tours.end(), *pointer_sorter ); - Tours.resize( max_num_paths ); + p_stat->OnEndBwLabeling(); + ClearBW(); + return false; } - return true; } + // final dominance + p_stat->OnStartBwDominance(); + apply_final_dominance_BW(); + p_stat->OnEndBwDominance(); + p_stat->OnEndBwLabeling(); + return ( v_dominance_manager_bw[source].size() < max_num_paths ); +} - // backward - template <class REF, class BManagerFW, class DManagerFW, class BManagerBW, class DManagerBW, class MManager> - void c_SPPRC_Solver<REF, BManagerFW, DManagerFW, BManagerBW, DManagerBW, MManager> - ::ClearBW() +template <class REF, class ExtManagerFW, class DManagerFW, class ExtManagerBW, class DManagerBW, class MManager, class StatManager> +bool c_SPPRC_Solver<REF, ExtManagerFW, DManagerFW, ExtManagerBW, DManagerBW, MManager, StatManager> +::WarmstartSolveBw(int source, int sink, int max_num_paths, int maxTime) +{ + c_Stopwatch timer_Solver; + timer_Solver.Start(); + p_stat->OnStartBwLabeling(); + int n = (int)v_dominance_manager_bw.size(); + if (!p_merge_manager) { - o_bucket_manager_bw.clear(); - int max_idx=(int) v_dominance_manager_bw.size(); - for (int i=0;i< max_idx;i++) - v_dominance_manager_bw[i].clear(); - i_extended_bw = 0; + cout << "Run SolveBidir(...) first. " << endl; + throw; } - - - template <class REF, class BManagerFW, class DManagerFW, class BManagerBW, class DManagerBW, class MManager> - bool c_SPPRC_Solver<REF, BManagerFW, DManagerFW, BManagerBW, DManagerBW, MManager> - ::SolveBw(int source, int sink, ResVectBW&& init_res, int maxnumpaths, int maxTime ) + for (int i = 0; i < n; i++) + for (t_labelBW* label_bw = v_dominance_manager_bw[i].begin(); label_bw; label_bw = v_dominance_manager_bw[i].next(label_bw)) + if (!p_merge_manager->BeforeHalfWayPointBW(*label_bw)) + o_extension_manager_bw.insert(label_bw); + o_extension_manager_bw.ResetBucketIndex(); + o_extension_manager_bw.IncreaseBucketIndex(); + for (int i = 0; i < n; i++) + v_dominance_manager_bw[i].PrepareForWarmstart(o_extension_manager_bw.GetBucketIndex()); + + t_labelBW* p_label = nullptr; + // iterate over the labels + ResVectBW new_res; + while ((p_label = o_extension_manager_bw.get_next())) { - bool solvedOptimal = true; - c_TimeInfo timer_Solver; - timer_Solver.Start(); - o_timer_bw_labeling.Start(); - ClearBW(); - int id = 0; - t_labelBW* p_label = new t_labelBW( id++, std::move(init_res), NULL, NULL ); - o_bucket_manager_bw.insert( p_label ); - v_dominance_manager_bw[sink].insert( p_label ); - // iterate over the labels - ResVectBW new_res; - while ( (p_label = o_bucket_manager_bw.get_next()) && (v_dominance_manager_bw[source].size()<maxnumpaths ) ) - { - i_extended_bw++; - // check global time - if( timer_Solver.Seconds() > maxTime ) + int id = p_label->Id(); + // dominance can be delayed to any point in time, the bucket manager decides when + if (o_extension_manager_bw.invoke_dominance_algorithm()) + { + p_stat->OnStartBwDominance(); + apply_dominance_BW(); + p_stat->OnEndBwDominance(); + if (v_dominance_manager_bw[source].size() >= max_num_paths) { - timer_Solver.Stop(); - o_timer_bw_labeling.Stop(); - ClearBW(); - return false; + p_stat->OnStartBwDominance(); + apply_final_dominance_BW(); + p_stat->OnEndBwDominance(); + p_stat->OnEndBwLabeling(); + return false; } - const ResVectBW& curr_res( *p_label ); - int node = ( p_label->generator_REF() ? p_label->generator_REF()->Tail() : sink ); - // iterate over backward star of the node - int max_idx = (int)v_bw_star[node].size(); - for ( int idx=0; idx<max_idx; idx++ ) + } + // has p_label been deleted? + if (o_extension_manager_bw.is_erased(id)) + continue; + // extension + i_extended_bw++; + const ResVectBW& curr_res(*p_label); + int node = (p_label->generator_REF() ? p_label->generator_REF()->Tail() : sink); + // iterate over backward star of the node + p_stat->OnStartBwPropagate(); + int max_idx = (int)v_bw_star[node].size(); + for (int idx = 0; idx<max_idx; idx++) + { + REF* p_ref = v_bw_star[node][idx]; + if (p_ref->PropagateBw(curr_res, new_res)) { - REF* p_ref = v_bw_star[node][idx]; - if ( p_ref->PropagateBw( curr_res, new_res ) ) - { - t_labelBW* new_label = new t_labelBW( id++, std::move(new_res), p_label, p_ref ); - o_bucket_manager_bw.insert( new_label ); - int new_node = p_ref->Tail(); - v_dominance_manager_bw[new_node].insert( new_label ); - } + p_label->set_extended(); + t_labelBW* new_label = new t_labelBW(i_id_bwd++, std::move(new_res), p_label, p_ref); +#ifdef SPPRC_CHECK_PATH + if (b_check_path) + CheckNewLabelBW(new_label); +#endif + o_extension_manager_bw.insert(new_label); + int new_node = p_ref->Tail(); + v_dominance_manager_bw[new_node].insert(new_label); } - p_label->setIsExtended(); - // dominance can be delayed to any point in time, the bucket manager decides when - if ( o_bucket_manager_bw.invoke_dominance_algorithm() ) - apply_dominance_BW(); } - if( v_dominance_manager_bw[source].size() >= maxnumpaths ) - solvedOptimal = false; - // final dominance - apply_dominance_BW(); - o_timer_bw_labeling.Stop(); - return solvedOptimal; + p_stat->OnEndBwPropagate(); + // check global time + if (timer_Solver.Seconds() > maxTime) + { + p_stat->OnEndBwLabeling(); + ClearBW(); + return false; + } } + // final dominance + p_stat->OnStartBwDominance(); + apply_final_dominance_BW(); + p_stat->OnEndBwDominance(); + p_stat->OnEndBwLabeling(); + return (v_dominance_manager_bw[source].size() < max_num_paths); +} - template <class REF, class BManagerFW, class DManagerFW, class BManagerBW, class DManagerBW, class MManager> - void c_SPPRC_Solver<REF, BManagerFW, DManagerFW, BManagerBW, DManagerBW, MManager> - ::apply_dominance_BW() - { - int max_idx=(int)v_dominance_manager_bw.size(); - for ( int i=0; i<max_idx; i++ ) - apply_dominance_BW(i); - } +template <class REF, class ExtManagerFW, class DManagerFW, class ExtManagerBW, class DManagerBW, class MManager, class StatManager> +void c_SPPRC_Solver<REF, ExtManagerFW, DManagerFW, ExtManagerBW, DManagerBW, MManager, StatManager> + ::apply_dominance_BW() +{ + int max_idx=(int)v_dominance_manager_bw.size(); + for ( int i=0; i<max_idx; i++ ) + apply_dominance_BW(i); +} - template <class REF, class BManagerFW, class DManagerFW, class BManagerBW, class DManagerBW, class MManager> - void c_SPPRC_Solver<REF, BManagerFW, DManagerFW, BManagerBW, DManagerBW, MManager> - ::apply_dominance_BW(int new_node) +template <class REF, class ExtManagerFW, class DManagerFW, class ExtManagerBW, class DManagerBW, class MManager, class StatManager> +void c_SPPRC_Solver<REF, ExtManagerFW, DManagerFW, ExtManagerBW, DManagerBW, MManager, StatManager> + ::apply_dominance_BW(int new_node) +{ + t_labelBW* label_to_delete = v_dominance_manager_bw[new_node].apply_dominance(o_extension_manager_bw.GetBucketIndex()); + + while ( label_to_delete ) { - t_labelBW* label_to_delete = v_dominance_manager_bw[new_node].apply_dominance(); - - while ( label_to_delete ) + if (!label_to_delete->is_extended()) { - o_bucket_manager_bw.erase( label_to_delete ); + o_extension_manager_bw.erase(label_to_delete); t_labelBW* next_label = label_to_delete->next(); - if( label_to_delete->isExtended() ){ - o_bucket_manager_bw.insertLabelStoredSinceExtended(label_to_delete); - } else{ - delete label_to_delete; - } + delete label_to_delete; label_to_delete = next_label; - /*o_bucket_manager_bw.erase( label_to_delete ); + } + else + { + //TODO: Collect Labels for later deleting t_labelBW* next_label = label_to_delete->next(); - delete label_to_delete; - label_to_delete = next_label;*/ + label_to_delete = next_label; } } +} - template <class REF, class BManagerFW, class DManagerFW, class BManagerBW, class DManagerBW, class MManager> - bool c_SPPRC_Solver<REF, BManagerFW, DManagerFW, BManagerBW, DManagerBW, MManager> - ::GetPathsBW( const int sink, std::vector<t_labelBW*>& Tours, std::function<bool (t_labelBW*,t_labelBW*)>* pointer_sorter, int max_num_paths ) +template <class REF, class ExtManagerFW, class DManagerFW, class ExtManagerBW, class DManagerBW, class MManager, class StatManager> +void c_SPPRC_Solver<REF, ExtManagerFW, DManagerFW, ExtManagerBW, DManagerBW, MManager, StatManager> +::apply_final_dominance_BW() +{ + int max_idx = (int)v_dominance_manager_bw.size(); + for (int i = 0; i<max_idx; i++) + apply_final_dominance_BW(i); +} + + +template <class REF, class ExtManagerFW, class DManagerFW, class ExtManagerBW, class DManagerBW, class MManager, class StatManager> +void c_SPPRC_Solver<REF, ExtManagerFW, DManagerFW, ExtManagerBW, DManagerBW, MManager, StatManager> +::apply_final_dominance_BW(int new_node) +{ + t_labelBW* label_to_delete = v_dominance_manager_bw[new_node].apply_final_dominance(o_extension_manager_bw.GetBucketIndex()); + + while (label_to_delete) { - t_labelBW* iter= v_dominance_manager_bw[sink].begin(); - while(iter) + if (!label_to_delete->is_extended()) { - Tours.push_back(iter); - iter=v_dominance_manager_bw[sink].next(); + o_extension_manager_bw.erase(label_to_delete); + t_labelBW* next_label = label_to_delete->next(); + delete label_to_delete; + label_to_delete = next_label; } - if ( max_num_paths>0 && (int)Tours.size() > max_num_paths ) + else { - if ( pointer_sorter ) - sort( Tours.begin(), Tours.end(), *pointer_sorter ); - Tours.resize( max_num_paths ); + //TODO: Collect Labels for later deleting + t_labelBW* next_label = label_to_delete->next(); + label_to_delete = next_label; } - return true; } +} + + +template <class REF, class ExtManagerFW, class DManagerFW, class ExtManagerBW, class DManagerBW, class MManager, class StatManager> +bool c_SPPRC_Solver<REF, ExtManagerFW, DManagerFW, ExtManagerBW, DManagerBW, MManager, StatManager> + ::GetPathsBW( const int sink, vector<t_labelBW*>& paths, function<bool (t_labelBW*,t_labelBW*)>* pointer_sorter, int max_num_paths ) +{ + t_labelBW* iter= v_dominance_manager_bw[sink].begin(); + while(iter) + { + paths.push_back(iter); + iter=v_dominance_manager_bw[sink].next(iter); + } + if ( (int)paths.size() > max_num_paths ) + { + if ( pointer_sorter ) + sort( paths.begin(), paths.end(), *pointer_sorter ); + paths.resize( max_num_paths ); + if (!pointer_sorter) + return false; + } + return true; +} - // bidirectional +// bidirectional - template <class REF, class BManagerFW, class DManagerFW, class BManagerBW, class DManagerBW, class MManager> - bool c_SPPRC_Solver<REF, BManagerFW, DManagerFW, BManagerBW, DManagerBW, MManager> - ::GetPathsBidir( const int sink, std::vector<std::pair<double, std::pair<t_labelFW*,t_labelBW*> > >& paths, - std::function<bool (std::pair<double,std::pair<t_labelFW*,t_labelBW*> >,std::pair<double,std::pair<t_labelFW*,t_labelBW*> >)>* pointer_sorter, int max_num_paths ) +template <class REF, class ExtManagerFW, class DManagerFW, class ExtManagerBW, class DManagerBW, class MManager, class StatManager> +bool c_SPPRC_Solver<REF, ExtManagerFW, DManagerFW, ExtManagerBW, DManagerBW, MManager, StatManager> + ::GetPathsBidir( const int sink, vector<pair<double, pair<t_labelFW*,t_labelBW*> > >& paths, + function<bool (pair<double,pair<t_labelFW*,t_labelBW*> >,pair<double,pair<t_labelFW*,t_labelBW*> >)>* pointer_sorter, int max_num_paths ) +{ + p_stat->OnStartBidirMerge(); + if ( !p_merge_manager ) + { + cout << "Run SolveBidir(...) first. " << endl; + throw; + } + int n = (int)v_dominance_manager_fw.size(); + double rdc = 0.0; + for (int i = 0; i < n; i++) { - o_timer_bidir_labeling_merge.Start(); - if ( !p_merge_manager ) + for (t_labelFW* label_fw = v_dominance_manager_fw[i].begin(); label_fw; label_fw = v_dominance_manager_fw[i].next(label_fw)) { - cout << "Run SolveBidir(...) first. " << endl; - throw; + if (p_merge_manager->MergeableFW(*label_fw)) + { + for (t_labelBW* label_bw = v_dominance_manager_bw[i].begin(); label_bw; label_bw = v_dominance_manager_bw[i].next(label_bw)) + { + if (p_merge_manager->MergeableBW(*label_bw) && p_merge_manager->Mergeable(*label_fw, *label_bw, rdc)) + paths.push_back(make_pair(rdc, make_pair(label_fw, label_bw))); + if ((int)paths.size()/2 > max_num_paths) + { + if (pointer_sorter) + sort(paths.begin(), paths.end(), *pointer_sorter); + paths.resize(max_num_paths); + } + if (!pointer_sorter && (int)paths.size() >= max_num_paths) + { + p_stat->OnEndBidirMerge(); + i_gen_paths = (int)paths.size(); + return false; + } + } + } } - int n = (int)v_dominance_manager_fw.size(); - double rdc = 0.0; - for (int i = 0; i < n; i++) + } + if ( (int)paths.size() > max_num_paths ) + { + if ( pointer_sorter ) + sort( paths.begin(), paths.end(), *pointer_sorter ); + paths.resize( max_num_paths ); + if (!pointer_sorter) + { + p_stat->OnEndBidirMerge(); + return false; + } + } + i_gen_paths = (int) paths.size(); + p_stat->OnEndBidirMerge(); + //sort(paths.begin(), paths.end(), *pointer_sorter); + return true; +} + + +template <class REF, class ExtManagerFW, class DManagerFW, class ExtManagerBW, class DManagerBW, class MManager, class StatManager> +bool c_SPPRC_Solver<REF, ExtManagerFW, DManagerFW, ExtManagerBW, DManagerBW, MManager, StatManager> +::GetPathsBidirBuckets(const int sink, vector<pair<double, pair<t_labelFW*, t_labelBW*> > >& paths, +function<bool(pair<double, pair<t_labelFW*, t_labelBW*> >, pair<double, pair<t_labelFW*, t_labelBW*> >)>* pointer_sorter, int max_num_paths) +{ + p_stat->OnStartBidirMerge(); + if (!p_merge_manager) + { + cout << "Run SolveBidir(...) first. " << endl; + throw; + } + int n = (int)v_dominance_manager_fw.size(); + double rdc = 0.0; + int numBuckets = p_merge_manager->NumBuckets(); + for (int i = 0; i < n; i++) + { + //Labels are sorted, if reverse order: reverse labels + v_dominance_manager_fw[i].ReverseAllBuckets(); + v_dominance_manager_bw[i].ReverseAllBuckets(); + for (int bucketI = 0; bucketI < numBuckets; ++bucketI) { - for (t_labelFW* label_fw = v_dominance_manager_fw[i].begin(); label_fw; label_fw = label_fw->next()) + for (t_labelFW* label_fw = v_dominance_manager_fw[i].begin(bucketI); label_fw; label_fw = v_dominance_manager_fw[i].next(bucketI, label_fw)) { if (p_merge_manager->MergeableFW(*label_fw)) - for (t_labelBW* label_bw = v_dominance_manager_bw[i].begin(); label_bw; label_bw = label_bw->next()) + { + for (auto bucketJ : p_merge_manager->BucketsThatFitForMerge(i, bucketI)) { - if (p_merge_manager->MergeableBW(*label_bw) && p_merge_manager->Mergeable(*label_fw, *label_bw, rdc)) - paths.push_back(make_pair(rdc, make_pair(label_fw, label_bw))); - if (max_num_paths > 0 && (int)paths.size() > 2 * max_num_paths) - { - if (pointer_sorter) - sort(paths.begin(), paths.end(), *pointer_sorter); - paths.resize(max_num_paths); - } - if (!pointer_sorter && max_num_paths > 0 && (int)paths.size() >= max_num_paths) + for (t_labelBW* label_bw = v_dominance_manager_bw[i].begin(bucketJ); label_bw; label_bw = v_dominance_manager_bw[i].next(bucketJ, label_bw)) { - o_timer_bidir_labeling_merge.Stop(); - i_gen_paths = (int)paths.size(); - return false; + if (p_merge_manager->BreakingCriterion(*label_fw, *label_bw)) + break; + if (p_merge_manager->MergeableBW(*label_bw) && p_merge_manager->Mergeable(*label_fw, *label_bw, rdc)) + paths.push_back(make_pair(rdc, make_pair(label_fw, label_bw))); + if ((int)paths.size() > 2 * max_num_paths) + { + if (pointer_sorter) + sort(paths.begin(), paths.end(), *pointer_sorter); + paths.resize(max_num_paths); + } + if (!pointer_sorter && (int)paths.size() >= max_num_paths) + { + p_stat->OnEndBidirMerge(); + i_gen_paths = (int)paths.size(); + return false; + } } } + } } } - if ( max_num_paths > 0 && (int)paths.size() > max_num_paths ) + } + if ((int)paths.size() > max_num_paths) + { + if (pointer_sorter) + sort(paths.begin(), paths.end(), *pointer_sorter); + paths.resize(max_num_paths); + if (!pointer_sorter) { - if ( pointer_sorter ) - sort( paths.begin(), paths.end(), *pointer_sorter ); - paths.resize( max_num_paths ); + p_stat->OnEndBidirMerge(); + return false; } - i_gen_paths = (int)paths.size(); - o_timer_bidir_labeling_merge.Stop(); - return true; } + i_gen_paths = (int)paths.size(); + p_stat->OnEndBidirMerge(); + //sort(paths.begin(), paths.end(), *pointer_sorter); + return true; +} - template <class REF, class BManagerFW, class DManagerFW, class BManagerBW, class DManagerBW, class MManager> - bool c_SPPRC_Solver<REF, BManagerFW, DManagerFW, BManagerBW, DManagerBW, MManager> - ::SolveBidir( MManager& merger, int source, int sink, ResVectFW&& init_res_fw, ResVectBW&& init_res_bw, int maxnumpaths, int maxTime ) // not generic! +template <class REF, class ExtManagerFW, class DManagerFW, class ExtManagerBW, class DManagerBW, class MManager, class StatManager> +bool c_SPPRC_Solver<REF, ExtManagerFW, DManagerFW, ExtManagerBW, DManagerBW, MManager, StatManager> + ::SolveBidir( MManager& merger, int source, int sink, ResVectFW&& init_res_fw, ResVectBW&& init_res_bw, int max_num_paths, int maxTime ) // not generic! +{ + p_stat->OnStartBidirLabeling(); + c_Stopwatch timer_Solver; + timer_Solver.Start(); + ClearFW(); + ClearBW(); + p_merge_manager = &merger; + i_hw = p_merge_manager->HalfwayPointFW(); + // init FW + i_id_fwd = 0; + t_labelFW* p_label_fw = new t_labelFW(i_id_fwd++, std::move(init_res_fw), nullptr, nullptr); +#ifdef SPPRC_CHECK_PATH + if(b_check_path) + CheckNewLabelFW(p_label_fw); +#endif + o_extension_manager_fw.insert( p_label_fw ); + v_dominance_manager_fw[source].insert( p_label_fw ); + // init BW + i_id_bwd = 0; + t_labelBW* p_label_bw = new t_labelBW(i_id_bwd++, std::move(init_res_bw), nullptr, nullptr); +#ifdef SPPRC_CHECK_PATH + if (b_check_path) + CheckNewLabelBW(p_label_bw); +#endif + + o_extension_manager_bw.insert(p_label_bw); + v_dominance_manager_bw[sink].insert(p_label_bw); + // iterate over the labels forward + p_stat->OnStartBidirFwLabeling(); + ResVectFW new_res; + while ( (p_label_fw = o_extension_manager_fw.get_next()) ) + { + int id = p_label_fw->Id(); + // dominance can be delayed to any point in time, the bucket manager decides when + if (o_extension_manager_fw.invoke_dominance_algorithm()) + { + p_stat->OnStartBidirFwDominance(); + apply_dominance_FW(); + p_stat->OnEndBidirFwDominance(); + if (v_dominance_manager_fw[sink].size() >= max_num_paths) + { + p_stat->OnStartBidirFwDominance(); + apply_final_dominance_FW(); + p_stat->OnEndBidirFwDominance(); + p_stat->OnEndBidirFwLabeling(); + return false; + } + } + // has p_label been deleted? + if (o_extension_manager_fw.is_erased(id)) + continue; + // extension + if (p_merge_manager->BeforeHalfWayPointFW(*p_label_fw)) + { + i_extended_fw++; + const ResVectFW& curr_res(*p_label_fw); + int node = (p_label_fw->generator_REF() ? p_label_fw->generator_REF()->Head() : source); + // iterate over forward star of the node + p_stat->OnStartBidirFwPropagate(); + int max_idx = (int)v_fw_star[node].size(); + for (int idx = 0; idx < max_idx; idx++) + { + REF* p_ref = v_fw_star[node][idx]; + if (p_ref->PropagateFw(curr_res, new_res)) + { + p_label_fw->set_extended(); + t_labelFW* new_label = new t_labelFW(i_id_fwd++, std::move(new_res), p_label_fw, p_ref); +#ifdef SPPRC_CHECK_PATH + if(b_check_path) + CheckNewLabelFW(new_label); +#endif + o_extension_manager_fw.insert(new_label); + int new_node = p_ref->Head(); + v_dominance_manager_fw[new_node].insert(new_label); + } + } + p_stat->OnEndBidirFwPropagate(); + } + // check global time + if (timer_Solver.Seconds() > maxTime) + { + p_stat->OnEndBidirLabeling(); + p_stat->OnEndBidirFwLabeling(); + ClearFW(); + return false; + } + } + // final dominance + p_stat->OnStartBidirFwDominance(); + apply_final_dominance_FW(); + p_stat->OnEndBidirFwDominance(); + p_stat->OnEndBidirFwLabeling(); + // + // iterate over the labels backward + // + p_stat->OnStartBidirBwLabeling(); + ResVectBW new_res_bw; + while ( (p_label_bw = o_extension_manager_bw.get_next()) ) + { + int id = p_label_bw->Id(); + // dominance can be delayed to any point in time, the bucket manager decides when + if (o_extension_manager_bw.invoke_dominance_algorithm()) + { + p_stat->OnStartBidirBwDominance(); + apply_dominance_BW(); + p_stat->OnEndBidirBwDominance(); + if (v_dominance_manager_bw[source].size() >= max_num_paths) + { + p_stat->OnStartBidirBwDominance(); + apply_final_dominance_BW(); + p_stat->OnEndBidirBwDominance(); + p_stat->OnEndBidirBwLabeling(); + return false; + } + } + // has p_label_bw been deleted? + if (o_extension_manager_bw.is_erased(id)) + continue; + // extension + if ( p_merge_manager->BeforeHalfWayPointBW( *p_label_bw ) ) + { + i_extended_bw++; + const ResVectBW& curr_res( *p_label_bw ); + int node = ( p_label_bw->generator_REF() ? p_label_bw->generator_REF()->Tail() : sink ); + // iterate over backward star of the node + p_stat->OnStartBidirBwPropagate(); + int max_idx = (int)v_bw_star[node].size(); + for ( int idx=0; idx<max_idx; idx++ ) + { + REF* p_ref = v_bw_star[node][idx]; + if ( p_ref->PropagateBw( curr_res, new_res_bw ) ) + { + p_label_bw->set_extended(); + t_labelBW* new_label = new t_labelBW(i_id_bwd++, std::move(new_res_bw), p_label_bw, p_ref); +#ifdef SPPRC_CHECK_PATH + if (b_check_path) + CheckNewLabelBW(new_label); +#endif + o_extension_manager_bw.insert( new_label ); + int new_node = p_ref->Tail(); + v_dominance_manager_bw[new_node].insert( new_label ); + } + } + p_stat->OnEndBidirBwPropagate(); + } + // check global time + if (timer_Solver.Seconds() > maxTime) + { + p_stat->OnEndBidirBwLabeling(); + ClearFW(); + ClearBW(); + return false; + } + } + // final dominance + p_stat->OnStartBidirBwDominance(); + apply_final_dominance_BW(); + p_stat->OnEndBidirBwDominance(); + p_stat->OnEndBidirBwLabeling(); + p_stat->OnEndBidirLabeling(); + return true; +} + + +template <class REF, class ExtManagerFW, class DManagerFW, class ExtManagerBW, class DManagerBW, class MManager, class StatManager> +bool c_SPPRC_Solver<REF, ExtManagerFW, DManagerFW, ExtManagerBW, DManagerBW, MManager, StatManager> + ::SolveBidir_DynamicHalfway(MManager& merger, int source, int sink, ResVectFW&& init_res_fw, ResVectBW&& init_res_bw, int max_num_paths, int maxTime ) +{ + c_Stopwatch timer_Solver; + timer_Solver.Start(); + p_stat->OnStartBidirLabeling(); + ClearFW(); + ClearBW(); + p_merge_manager = &merger; + // init FW + i_id_fwd = 0; + t_labelFW* p_label_fw = new t_labelFW(i_id_fwd++, std::move(init_res_fw), nullptr, nullptr); +#ifdef SPPRC_CHECK_PATH + if ( b_check_path) + CheckNewLabelFW(p_label_fw); +#endif + o_extension_manager_fw.insert( p_label_fw ); + v_dominance_manager_fw[source].insert( p_label_fw ); + ResVectFW new_res_fw; + // init BW + i_id_bwd = 0; + t_labelBW* p_label_bw = new t_labelBW(i_id_bwd++, std::move(init_res_bw), nullptr, nullptr); +#ifdef SPPRC_CHECK_PATH + if (b_check_path) + CheckNewLabelBW(p_label_bw); +#endif + o_extension_manager_bw.insert( p_label_bw ); + v_dominance_manager_bw[sink].insert( p_label_bw ); + ResVectBW new_res_bw; + // the dynamic part + p_merge_manager->SetHalfwayPointFW( (*p_label_bw)() ); + p_merge_manager->SetHalfwayPointBW( (*p_label_fw)() ); + bool forward = true; + do { - c_TimeInfo timer_Solver; - timer_Solver.Start(); - ClearFW(); - ClearBW(); - p_merge_manager = &merger; - i_hw = p_merge_manager->HalfwayPointFW(); - // init FW - int id_fw = 0; - t_labelFW* p_label_fw = new t_labelFW( id_fw++, std::move(init_res_fw), NULL, NULL ); - o_bucket_manager_fw.insert( p_label_fw ); - v_dominance_manager_fw[source].insert( p_label_fw ); - // init BW - int id_bw = 0; - t_labelBW* p_label_bw = new t_labelBW(id_bw++, std::move(init_res_bw), NULL, NULL); - o_bucket_manager_bw.insert(p_label_bw); - v_dominance_manager_bw[sink].insert(p_label_bw); - // iterate over the labels forward - o_timer_bidir_labeling_fw_part.Start(); - ResVectFW new_res; - while ( (p_label_fw = o_bucket_manager_fw.get_next()) && (v_dominance_manager_fw[sink].size()<maxnumpaths ) ) - { - // check global time - if( timer_Solver.Seconds() > maxTime ){ - timer_Solver.Stop(); - o_timer_bidir_labeling_fw_part.Stop(); - ClearFW(); - return false; + if ( forward ) + { + p_label_fw = o_extension_manager_fw.get_next(); + if (!p_label_fw) + { + forward = false; + continue; + } + int id = p_label_fw->Id(); + // dominance can be delayed to any point in time, the bucket manager decides when + if (o_extension_manager_fw.invoke_dominance_algorithm()) + { + p_stat->OnStartBidirFwDominance(); + apply_dominance_FW(); + p_stat->OnEndBidirFwDominance(); + if (v_dominance_manager_fw[sink].size() >= max_num_paths) + { + p_stat->OnStartBidirFwDominance(); + apply_final_dominance_FW(); + p_stat->OnEndBidirFwDominance(); + p_stat->OnStartBidirBwDominance(); + apply_final_dominance_BW(); + p_stat->OnEndBidirBwDominance(); + p_stat->OnEndBidirLabeling(); + return false; + } } + // has p_label_fw been deleted? + if (o_extension_manager_fw.is_erased(id)) + continue; + // extension if ( p_merge_manager->BeforeHalfWayPointFW( *p_label_fw ) ) { i_extended_fw++; const ResVectFW& curr_res( *p_label_fw ); int node = ( p_label_fw->generator_REF() ? p_label_fw->generator_REF()->Head() : source ); - // iterate over forward star of the node + p_stat->OnStartBidirFwPropagate(); int max_idx = (int)v_fw_star[node].size(); for ( int idx=0; idx<max_idx; idx++ ) { REF* p_ref = v_fw_star[node][idx]; - if ( p_ref->PropagateFw( curr_res, new_res ) ) + if ( p_ref->PropagateFw( curr_res, new_res_fw ) ) { - t_labelFW* new_label = new t_labelFW( id_fw++, std::move(new_res), p_label_fw, p_ref ); - o_bucket_manager_fw.insert( new_label ); + p_label_fw->set_extended(); + t_labelFW* new_label = new t_labelFW(i_id_fwd++, std::move(new_res_fw), p_label_fw, p_ref); +#ifdef SPPRC_CHECK_PATH + if (b_check_path) + CheckNewLabelFW(new_label); +#endif + o_extension_manager_fw.insert( new_label ); int new_node = p_ref->Head(); v_dominance_manager_fw[new_node].insert( new_label ); } } - p_label_fw->setIsExtended(); + p_stat->OnEndBidirFwPropagate(); } - // dominance can be delayed to any point in time, the bucket manager decides when - if ( o_bucket_manager_fw.invoke_dominance_algorithm() ) - apply_dominance_FW(); - } - if( v_dominance_manager_fw[sink].size() >= maxnumpaths ) - { - apply_dominance_FW(); - apply_dominance_BW(); - return false; + p_merge_manager->SetHalfwayPointBW( min( (*p_label_fw)(), p_merge_manager->HalfwayPointFW() ) ); } - // final dominance - apply_dominance_FW(); - o_timer_bidir_labeling_fw_part.Stop(); - - // iterate over the labels backward - o_timer_bidir_labeling_bw_part.Start(); - ResVectBW new_res_bw; - while ( (p_label_bw = o_bucket_manager_bw.get_next()) ) - { - // check global time - if( timer_Solver.Seconds() > maxTime ) + else + { + // backward + p_label_bw = o_extension_manager_bw.get_next(); + if (!p_label_bw) { - timer_Solver.Stop(); - o_timer_bidir_labeling_bw_part.Stop(); - ClearFW(); - ClearBW(); - return false; + forward = true; + continue; + } + int id = p_label_bw->Id(); + // dominance can be delayed to any point in time, the bucket manager decides when + if (o_extension_manager_bw.invoke_dominance_algorithm()) + { + p_stat->OnStartBidirBwDominance(); + apply_dominance_BW(); + p_stat->OnEndBidirBwDominance(); } + // has p_label_bw been deleted? + if (o_extension_manager_bw.is_erased(id)) + continue; + // extension... if ( p_merge_manager->BeforeHalfWayPointBW( *p_label_bw ) ) { i_extended_bw++; const ResVectBW& curr_res( *p_label_bw ); int node = ( p_label_bw->generator_REF() ? p_label_bw->generator_REF()->Tail() : sink ); - // iterate over backward star of the node + p_stat->OnStartBidirBwPropagate(); int max_idx = (int)v_bw_star[node].size(); for ( int idx=0; idx<max_idx; idx++ ) { REF* p_ref = v_bw_star[node][idx]; if ( p_ref->PropagateBw( curr_res, new_res_bw ) ) { - t_labelBW* new_label = new t_labelBW( id_bw++, std::move(new_res_bw), p_label_bw, p_ref ); - o_bucket_manager_bw.insert( new_label ); + p_label_bw->set_extended(); + t_labelBW* new_label = new t_labelBW(i_id_bwd++, std::move(new_res_bw), p_label_bw, p_ref); +#ifdef SPPRC_CHECK_PATH + if (b_check_path) + CheckNewLabelBW(new_label); +#endif + o_extension_manager_bw.insert( new_label ); int new_node = p_ref->Tail(); v_dominance_manager_bw[new_node].insert( new_label ); } } - p_label_bw->setIsExtended(); + p_stat->OnEndBidirBwPropagate(); } - // dominance can be delayed to any point in time, the bucket manager decides when - if ( o_bucket_manager_bw.invoke_dominance_algorithm() ) - apply_dominance_BW(); + p_merge_manager->SetHalfwayPointFW( max( (*p_label_bw)(), p_merge_manager->HalfwayPointBW() ) ); + } + // Decide on whether we go forward or backward + forward = ( o_extension_manager_fw.OpenLabels() < o_extension_manager_bw.OpenLabels() ); + if ( forward && !p_label_fw ) + forward = false; + if ( !forward && !p_label_bw ) + forward = true; + // check global time + if (timer_Solver.Seconds() > maxTime) + { + p_stat->OnEndBidirLabeling(); + ClearFW(); + ClearBW(); + return false; } - // final dominance - apply_dominance_BW(); - o_timer_bidir_labeling_bw_part.Stop(); - return true; } + while (p_label_fw || p_label_bw); + // final dominance + p_stat->OnStartBidirFwDominance(); + apply_final_dominance_FW(); + p_stat->OnEndBidirFwDominance(); + p_stat->OnStartBidirBwDominance(); + apply_final_dominance_BW(); + p_stat->OnEndBidirBwDominance(); + i_hw = (p_merge_manager->HalfwayPointFW() + p_merge_manager->HalfwayPointBW()) /2; + p_stat->OnEndBidirLabeling(); + return true; +} +// bidir symmetric - template <class REF, class BManagerFW, class DManagerFW, class BManagerBW, class DManagerBW, class MManager> - bool espprc::c_SPPRC_Solver<REF, BManagerFW, DManagerFW, BManagerBW, DManagerBW, MManager>::SolveBidir_DynamicHalfway(MManager& merger, int source, int sink, ResVectFW&& init_res_fw, ResVectBW&& init_res_bw, int maxnumpaths /*= -1*/, int maxTime /*= numeric_limits<int>::max() */) - { - bool solvedOptimal = true; - c_TimeInfo timer_Solver; - timer_Solver.Start(); - o_timer_dyn_bidir_labeling.Start(); - ClearFW(); - ClearBW(); - p_merge_manager = &merger; - // init FW - int id_fw = 0; - t_labelFW* p_label_fw = new t_labelFW( id_fw++, std::move(init_res_fw), NULL, NULL ); - o_bucket_manager_fw.insert( p_label_fw ); - v_dominance_manager_fw[source].insert( p_label_fw ); - ResVectFW new_res_fw; - // init BW - int id_bw = 0; - t_labelBW* p_label_bw = new t_labelBW( id_bw++, std::move(init_res_bw), NULL, NULL ); - o_bucket_manager_bw.insert( p_label_bw ); - v_dominance_manager_bw[sink].insert( p_label_bw ); - ResVectBW new_res_bw; - // the dynamic part - p_merge_manager->SetHalfwayPointFW( (*p_label_bw)() ); - p_merge_manager->SetHalfwayPointBW( (*p_label_fw)() ); - p_label_fw = o_bucket_manager_fw.get_next(); - p_label_bw = o_bucket_manager_bw.get_next(); - bool forward = true; - while ( ( p_label_fw || p_label_bw ) && ( v_dominance_manager_fw[sink].size()<maxnumpaths ) ) +template <class REF, class ExtManagerFW, class DManagerFW, class ExtManagerBW, class DManagerBW, class MManager, class StatManager> +bool c_SPPRC_Solver<REF, ExtManagerFW, DManagerFW, ExtManagerBW, DManagerBW, MManager, StatManager> + ::SolveBidir_Symmetric( MManager& merger, int source, int sink, ResVectFW&& init_res, int max_num_paths, int maxTime ) +{ + if ( !is_same<ExtManagerFW,ExtManagerBW>::value + || !is_same<DManagerFW,DManagerBW>::value + || !is_same<ResVectFW,ResVectBW>::value + || !is_same<t_labelFW,t_labelBW>::value ) + { + cout << "SolveBidir_Symmetric only applicable for symmetric SPPRCs" << endl; + throw; + } + // safe now + c_Stopwatch timer; + timer.Start(); + p_stat->OnStartBidirLabeling(); + p_stat->OnStartBidirFwLabeling(); + p_merge_manager = &merger; + ClearFW(); + ResVectFW copy_res( init_res ); + i_id_fwd = 0; + t_labelFW* p_label = new t_labelFW(i_id_fwd++, std::move(init_res), nullptr, nullptr); +#ifdef SPPRC_CHECK_PATH + if ( b_check_path) + CheckNewLabelFW(p_label); +#endif + o_extension_manager_fw.insert( p_label ); + v_dominance_manager_fw[source].insert( p_label ); + // iterate over the labels + ResVectFW new_res; + while (( p_label = o_extension_manager_fw.get_next() )) + { + int id = p_label->Id(); + // dominance can be delayed to any point in time, the bucket manager decides when + if (o_extension_manager_fw.invoke_dominance_algorithm()) + { + apply_dominance_FW(); + if (v_dominance_manager_fw[sink].size() >= max_num_paths) + break; + } + // has p_label been deleted? + if (o_extension_manager_fw.is_erased(id)) + continue; + // extension... + if ( p_merge_manager->BeforeHalfWayPointFW( *p_label ) ) { + i_extended_fw++; // check global time - if( timer_Solver.Seconds() > maxTime ) + if( timer.Seconds() > maxTime ) { - timer_Solver.Stop(); - o_timer_dyn_bidir_labeling.Stop(); + p_stat->OnEndBidirLabeling(); + p_stat->OnEndBidirFwLabeling(); ClearFW(); - ClearBW(); return false; } - if ( forward ) + const ResVectFW& curr_res( *p_label ); + int node = ( p_label->generator_REF() ? p_label->generator_REF()->Head() : source ); + // iterate over forward star of the node + p_stat->OnStartBidirFwPropagate(); + int max_idx = (int)v_fw_star[node].size(); + for ( int idx=0; idx<max_idx; idx++ ) { - if ( p_merge_manager->BeforeHalfWayPointFW( *p_label_fw ) ) + REF* p_ref = v_fw_star[node][idx]; + if ( p_ref->PropagateFw( curr_res, new_res ) ) { - i_extended_fw++; - const ResVectFW& curr_res( *p_label_fw ); - int node = ( p_label_fw->generator_REF() ? p_label_fw->generator_REF()->Head() : source ); - - // iterate over forward star of the node - int max_idx = (int)v_fw_star[node].size(); - for ( int idx=0; idx<max_idx; idx++ ) - { - REF* p_ref = v_fw_star[node][idx]; - if ( p_ref->PropagateFw( curr_res, new_res_fw ) ) - { - t_labelFW* new_label = new t_labelFW( id_fw++, std::move(new_res_fw), p_label_fw, p_ref ); - o_bucket_manager_fw.insert( new_label ); - int new_node = p_ref->Head(); - v_dominance_manager_fw[new_node].insert( new_label ); - } - } - p_label_fw->setIsExtended(); + p_label->set_extended(); + t_labelFW* new_label = new t_labelFW(i_id_fwd++, std::move(new_res), p_label, p_ref); +#ifdef SPPRC_CHECK_PATH + if(b_check_path) + CheckNewLabelFW(new_label); +#endif + o_extension_manager_fw.insert( new_label ); + int new_node = p_ref->Head(); + v_dominance_manager_fw[new_node].insert( new_label ); } - // dominance can be delayed to any point in time, the bucket manager decides when - if ( o_bucket_manager_fw.invoke_dominance_algorithm() ) - apply_dominance_FW(); - p_merge_manager->SetHalfwayPointBW( min( (*p_label_fw)(), p_merge_manager->HalfwayPointFW() ) ); - p_label_fw = o_bucket_manager_fw.get_next(); } - else - { // backward - if ( p_merge_manager->BeforeHalfWayPointBW( *p_label_bw ) ) - { - i_extended_bw++; - const ResVectBW& curr_res( *p_label_bw ); - int node = ( p_label_bw->generator_REF() ? p_label_bw->generator_REF()->Tail() : sink ); + p_stat->OnEndBidirFwPropagate(); + } + } + // add one more label at sink + t_labelFW* dest_label = new t_labelFW(i_id_fwd++, std::move(copy_res), nullptr, nullptr); +#ifdef SPPRC_CHECK_PATH + if(b_check_path) + CheckNewLabelFW(dest_label); +#endif + o_extension_manager_fw.insert( dest_label ); + v_dominance_manager_fw[sink].insert( dest_label ); + // final dominance + p_stat->OnStartBidirFwDominance(); + apply_dominance_FW(); + p_stat->OnEndBidirFwDominance(); + p_stat->OnEndBidirFwLabeling(); + p_stat->OnEndBidirLabeling(); + return (v_dominance_manager_fw[sink].size() < max_num_paths ); +} + - // iterate over backward star of the node - int max_idx = (int)v_bw_star[node].size(); - for ( int idx=0; idx<max_idx; idx++ ) +template <class REF, class ExtManagerFW, class DManagerFW, class ExtManagerBW, class DManagerBW, class MManager, class StatManager> +bool c_SPPRC_Solver<REF, ExtManagerFW, DManagerFW, ExtManagerBW, DManagerBW, MManager, StatManager> + ::GetPathsBidir_Symmetric( const int sink, vector<pair<double, pair<t_labelFW*,t_labelBW*> > >& paths, function<bool (t_labelFW*, t_labelBW*)>* pointer_sorter_merge, function<bool (pair<double,pair<t_labelFW*,t_labelBW*> >, pair<double,pair<t_labelFW*,t_labelBW*> > )>* pointer_sorter, int max_num_paths) +{ + if ( !is_same<ExtManagerFW,ExtManagerBW>::value + || !is_same<DManagerFW,DManagerBW>::value + || !is_same<ResVectFW,ResVectBW>::value + || !is_same<t_labelFW,t_labelBW>::value ) + { + cout << "GetPathsBidir_Symmetric only applicable for symmetric SPPRCs" << endl; + throw; + } + // safe now + p_stat->OnStartBidirMerge(); + if ( !p_merge_manager ) + { + cout << "Run SolveBidir_Symmetric(...) first. " << endl; + throw; + } + int n = (int)v_dominance_manager_fw.size(); + double rdc = 0.0; + for (int i = 0; i < n; i++) + { + v_dominance_manager_fw[i].Sort(pointer_sorter_merge); + for (t_labelFW* label_fw = v_dominance_manager_fw[i].begin(); label_fw; label_fw = v_dominance_manager_fw[i].next(label_fw)) + { + if (p_merge_manager->MergeableFW(*label_fw)) + { + for (t_labelBW* label_bw = label_fw; label_bw; label_bw = v_dominance_manager_fw[i].next(label_bw)) + { + if (p_merge_manager->BreakingCriterion(*label_fw, *label_bw)) + break; + if (p_merge_manager->MergeableBW(*label_bw) && p_merge_manager->Mergeable(*label_fw, *label_bw, rdc)) + paths.push_back(make_pair(rdc, make_pair(label_fw, label_bw))); + if ((int)paths.size() > 2 * max_num_paths) { - REF* p_ref = v_bw_star[node][idx]; - if ( p_ref->PropagateBw( curr_res, new_res_bw ) ) - { - t_labelBW* new_label = new t_labelBW( id_bw++, std::move(new_res_bw), p_label_bw, p_ref ); - o_bucket_manager_bw.insert( new_label ); - int new_node = p_ref->Tail(); - v_dominance_manager_bw[new_node].insert( new_label ); - } + if (pointer_sorter) + sort(paths.begin(), paths.end(), *pointer_sorter); + paths.resize(max_num_paths); + } + if (!pointer_sorter && (int)paths.size() >= max_num_paths) + { + p_stat->OnEndBidirMerge(); + i_gen_paths = (int)paths.size(); + return false; } - p_label_bw->setIsExtended(); } - // dominance can be delayed to any point in time, the bucket manager decides when - if ( o_bucket_manager_bw.invoke_dominance_algorithm() ) - apply_dominance_BW(); - p_merge_manager->SetHalfwayPointFW( max( (*p_label_bw)(), p_merge_manager->HalfwayPointBW() ) ); - p_label_bw = o_bucket_manager_bw.get_next(); } - // Decide on whether we go forward or backward - forward = ( o_bucket_manager_fw.OpenLabels() < o_bucket_manager_bw.OpenLabels() ); - if ( forward && !p_label_fw ) - forward = false; - if ( !forward && !p_label_bw ) - forward = true; } - if( v_dominance_manager_fw[sink].size() >= maxnumpaths ){ - solvedOptimal = false; - } - // final dominance - apply_dominance_FW(); - apply_dominance_BW(); - o_timer_dyn_bidir_labeling.Stop(); - i_hw = (p_merge_manager->HalfwayPointFW() + p_merge_manager->HalfwayPointBW()) /2; - return solvedOptimal; } - - // IO - - template <class REF, class BManagerFW, class DManagerFW, class BManagerBW, class DManagerBW, class MManager> - void c_SPPRC_Solver<REF, BManagerFW, DManagerFW, BManagerBW, DManagerBW, MManager> - ::OutputInStream(std::ostream& s) const + // too many? + if ( (int)paths.size() > max_num_paths ) { - int max_idx=(int)v_dominance_manager_fw.size(); - for (int i=0;i<max_idx;i++) - { - s << "Node: " << i << endl; - v_dominance_manager_fw[i].OutputInStream(s); + if ( pointer_sorter ) + sort( paths.begin(), paths.end(), *pointer_sorter ); + paths.resize( max_num_paths ); + if (!pointer_sorter) + { + p_stat->OnEndBidirMerge(); + return false; } } + i_gen_paths = (int)paths.size(); + p_stat->OnEndBidirMerge(); + return true; +} - template <class REF, class BManagerFW, class DManagerFW, class BManagerBW, class DManagerBW, class MManager> - void c_SPPRC_Solver<REF, BManagerFW, DManagerFW, BManagerBW, DManagerBW, MManager> - ::OutputGraphML(const char* filename) +template <class REF, class ExtManagerFW, class DManagerFW, class ExtManagerBW, class DManagerBW, class MManager, class StatManager> +bool c_SPPRC_Solver<REF, ExtManagerFW, DManagerFW, ExtManagerBW, DManagerBW, MManager, StatManager> +::GetPathsBidirBuckets_Symmetric(const int sink, vector<pair<double, pair<t_labelFW*, t_labelBW*> > >& paths, function<bool(t_labelFW*, t_labelBW*)>* pointer_sorter_merge, function<bool(pair<double, pair<t_labelFW*, t_labelBW*> >, pair<double, pair<t_labelFW*, t_labelBW*> >)>* pointer_sorter, int max_num_paths) +{ + if (!is_same<ExtManagerFW, ExtManagerBW>::value + || !is_same<DManagerFW, DManagerBW>::value + || !is_same<ResVectFW, ResVectBW>::value + || !is_same<t_labelFW, t_labelBW>::value) { - using namespace graphml; - c_GraphML g( filename); - //Nodes - int max_idx=(int)v_dominance_manager_fw.size(); - for (int i=0; i<max_idx;i++) - { - nodeproperties np; - np.bordercolor = Color( "Black" ); - np.coord_x = i*10; - np.coord_y = i*10; - g.AddNode( i, np ); - } - //Arcs - for (int i=0; i<max_idx;i++) + cout << "GetPathsBidir_Symmetric only applicable for symmetric SPPRCs" << endl; + throw; + } + // safe now + p_stat->OnStartBidirMerge(); + if (!p_merge_manager) + { + cout << "Run SolveBidir_Symmetric(...) first. " << endl; + throw; + } + int n = (int)v_dominance_manager_fw.size(); + double rdc = 0.0; + int numBuckets = p_merge_manager->NumBuckets(); + for (int i = 0; i < n; i++) + { + //Labels are sorted, in reverse order: reverse labels + v_dominance_manager_fw[i].ReverseAllBuckets(); + for (int bucketI = 0; bucketI < numBuckets; ++bucketI) { - int max_idx2=(int) v_fw_star[i].size(); - for (int j=0; j<max_idx2;j++) - { - - linkproperties lp; - lp.linecolor = Color("Black"); - lp.linewidth = 1.5; - g.AddArc( v_fw_star[i][j]->Tail(), v_fw_star[i][j]->Head(), lp ); + for (t_labelFW* label_fw = v_dominance_manager_fw[i].begin(bucketI); label_fw; label_fw = v_dominance_manager_fw[i].next(bucketI, label_fw)) + { + if (p_merge_manager->MergeableFW(*label_fw)) + { + for (auto bucketJ : p_merge_manager->BucketsThatFitForMerge(i, bucketI)) + { + for (t_labelBW* label_bw = (bucketI == bucketJ ? label_fw : v_dominance_manager_fw[i].begin(bucketJ)); label_bw; label_bw = v_dominance_manager_fw[i].next(bucketJ, label_bw)) + { + if (p_merge_manager->BreakingCriterion(*label_fw, *label_bw)) + break; + if (p_merge_manager->MergeableBW(*label_bw) && p_merge_manager->Mergeable(*label_fw, *label_bw, rdc)) + paths.push_back(make_pair(rdc, make_pair(label_fw, label_bw))); + if ((int)paths.size() > 2 * max_num_paths) + { + if (pointer_sorter) + sort(paths.begin(), paths.end(), *pointer_sorter); + paths.resize(max_num_paths); + } + + if (!pointer_sorter && (int)paths.size() >= max_num_paths) + { + p_stat->OnEndBidirMerge(); + i_gen_paths = (int)paths.size(); + return false; + } + } + } + } } } } - - - template <class REF, class BManagerFW, class DManagerFW, class BManagerBW, class DManagerBW, class MManager> - void espprc::c_SPPRC_Solver<REF, BManagerFW, DManagerFW, BManagerBW, DManagerBW, MManager>::ResetStatistics() + // too many? + if ((int)paths.size() > max_num_paths) { - o_timer_fw_labeling.Reset(); - o_timer_bw_labeling.Reset(); - o_timer_bidir_labeling_fw_part.Reset(); - o_timer_bidir_labeling_bw_part.Reset(); - o_timer_bidir_labeling_merge.Reset(); - o_timer_dyn_bidir_labeling.Reset(); + if (pointer_sorter) + sort(paths.begin(), paths.end(), *pointer_sorter); + paths.resize(max_num_paths); + if (!pointer_sorter) + { + p_stat->OnEndBidirMerge(); + return false; + } } - -//}; - - - - - - - + i_gen_paths = (int)paths.size(); + p_stat->OnEndBidirMerge(); + return true; +} +// IO -#ifdef DebugAnka -template <class REF, class BManagerFW, class DManagerFW, class BManagerBW, class DManagerBW, class MManager> -void c_SPPRC_Solver<REF, BManagerFW, DManagerFW, BManagerBW, DManagerBW, MManager> - ::apply_dominance_FW_TakeCare( int new_node, int labelToPayAttention ) +template <class REF, class ExtManagerFW, class DManagerFW, class ExtManagerBW, class DManagerBW, class MManager, class StatManager> +void c_SPPRC_Solver<REF, ExtManagerFW, DManagerFW, ExtManagerBW, DManagerBW, MManager, StatManager> + ::OutputInStream(ostream& s) const { - t_labelFW* label_to_delete = v_dominance_manager_fw[new_node].apply_dominance( labelToPayAttention ); - //v_dominance_manager[new_node].OutputInStream(cout); - while ( label_to_delete ) - { - o_bucket_manager_fw.erase( label_to_delete ); - t_labelFW* next_label = label_to_delete->next(); - if( label_to_delete->isExtended() ){ - o_bucket_manager_fw.insertLabelStoredSinceExtended(label_to_delete); - } else{ - delete label_to_delete; + int max_idx_fw=(int)v_dominance_manager_fw.size(); + int max_idx_bw=(int)v_dominance_manager_bw.size(); + for (int i=0;i<max(max_idx_fw, max_idx_bw);i++) + { + s << "Node: " << i << endl; + if (i < max_idx_fw) + { + s << "Forward: " << endl; + v_dominance_manager_fw[i].OutputInStream(s); + } + if (i < max_idx_bw) + { + s << "Backward: " << endl; + v_dominance_manager_bw[i].OutputInStream(s); } - label_to_delete = next_label; } } -template <class REF, class BManagerFW, class DManagerFW, class BManagerBW, class DManagerBW, class MManager> -void c_SPPRC_Solver<REF, BManagerFW, DManagerFW, BManagerBW, DManagerBW, MManager> - ::apply_dominance_FW_TakeCare(int labelToPayAttention) +template <class REF, class ExtManagerFW, class DManagerFW, class ExtManagerBW, class DManagerBW, class MManager, class StatManager> +void c_SPPRC_Solver<REF, ExtManagerFW, DManagerFW, ExtManagerBW, DManagerBW, MManager, StatManager> + ::OutputGraphML(string filename) { + using namespace graphml; + c_GraphML g( filename); + //Nodes int max_idx=(int)v_dominance_manager_fw.size(); - for ( int i=0; i<max_idx; i++ ) - if( v_domNodes_FW[i] ) - apply_dominance_FW_TakeCare(i, labelToPayAttention ); -} - -template <class REF, class BManagerFW, class DManagerFW, class BManagerBW, class DManagerBW, class MManager> -void c_SPPRC_Solver<REF, BManagerFW, DManagerFW, BManagerBW, DManagerBW, MManager> - ::apply_dominance_BW_TakeCare( int new_node, int labelToPayAttention ) -{ - t_labelBW* label_to_delete = v_dominance_manager_bw[new_node].apply_dominance( labelToPayAttention ); - //v_dominance_manager[new_node].OutputInStream(cout); - while ( label_to_delete ) + for (int i=0; i<max_idx;i++) { - o_bucket_manager_bw.erase( label_to_delete ); - t_labelBW* next_label = label_to_delete->next(); - if( label_to_delete->isExtended() ){ - o_bucket_manager_bw.insertLabelStoredSinceExtended(label_to_delete); - } else{ - delete label_to_delete; + nodeproperties np; + np.bordercolor = Color( "Black" ); + np.coord_x = i*10; + np.coord_y = i*10; + g.AddNode( i, np ); + } + //Arcs + for (int i=0; i<max_idx;i++) + { + int max_idx2=(int) v_fw_star[i].size(); + for (int j=0; j<max_idx2;j++) + { + linkproperties lp; + lp.linecolor = Color("Black"); + lp.linewidth = 1.5; + g.AddArc( v_fw_star[i][j]->Tail(), v_fw_star[i][j]->Head(), lp ); } - label_to_delete = next_label; } } +// DEBUGGING -template <class REF, class BManagerFW, class DManagerFW, class BManagerBW, class DManagerBW, class MManager> -void c_SPPRC_Solver<REF, BManagerFW, DManagerFW, BManagerBW, DManagerBW, MManager> - ::apply_dominance_BW_TakeCare(int labelToPayAttention) -{ - int max_idx=(int)v_dominance_manager_bw.size(); - for ( int i=0; i<max_idx; i++ ) - apply_dominance_BW_TakeCare(i, labelToPayAttention ); -} - +#ifdef SPPRC_CHECK_PATH -template <class REF, class BManagerFW, class DManagerFW, class BManagerBW, class DManagerBW, class MManager> -void c_SPPRC_Solver<REF, BManagerFW, DManagerFW, BManagerBW, DManagerBW, MManager> - ::SolveFw( int source, int sink, ResVectFW&& init_res, const vector<int>& expectedTour, int maxnumpaths) +template<class REF, class ExtManagerFW, class DManagerFW, class ExtManagerBW, class DManagerBW, class MManager, class StatManager> +inline bool c_SPPRC_Solver<REF, ExtManagerFW, DManagerFW, ExtManagerBW, DManagerBW, MManager, StatManager>::CheckNewLabelFW(t_labelFW* label) { - ClearFW(); - int id = 0; - t_labelFW* p_label = new t_labelFW( id++, std::move(init_res), NULL, NULL ); - o_bucket_manager_fw.insert( p_label ); - v_dominance_manager_fw[source].insert( p_label ); - // iterate over the labels - ResVectFW new_res; - int newLabelIdFw = -1; - while ( (p_label = o_bucket_manager_fw.get_next()) && (v_dominance_manager_fw[sink].size()<maxnumpaths ) ) - { - const ResVectFW& curr_res( *p_label ); - int node = ( p_label->generator_REF() ? p_label->generator_REF()->Head() : source ); - - bool onExpectedTour = false; - int nextNode = -1; - if(p_label->generator_REF() && p_label->containsRoute(expectedTour, nextNode)){ - //cout << "Tour reached until node " << node << endl; - onExpectedTour = true; - } - - // iterate over forward star of the node - int max_idx = (int)v_fw_star[node].size(); - for ( int idx=0; idx<max_idx; idx++ ) + if (label->generator_REF()) + { + if (label->predecessor()->b_check_required) { - REF* p_ref = v_fw_star[node][idx]; - if( onExpectedTour && p_ref->Head() == nextNode && p_ref->Tail() == node){ - cout << "Achtung" << endl; - } - - /*if( p_ref->Head() == 79 && p_ref->Tail() == 22 ){ - onExpectedTour = true; - nextNode = 33; - cout << "Achtung" << endl; - }*/ - if ( p_ref->PropagateFw( curr_res, new_res ) ) + for ( int i=0; i<v_path_to_check.size(); i++ ) { - int new_node = p_ref->Head(); - t_labelFW* new_label = new t_labelFW( id++, move(new_res), p_label, p_ref ); - - if( onExpectedTour && p_ref->Head() == nextNode && p_ref->Tail() == node){ - newLabelIdFw = new_label->Id(); - cout << "Extended to label " << new_label->Id() << " of node " << new_node << endl; - /*cout << " with costs: " << new_label->Cost() << ", time: " << new_label->Time() - << ", ll: " << new_label->LorryLoad() << ", tl: " << new_label->TrailerLoad() << endl;*/ - } - /*if( useBounds && p_ref->o_instance.IsDelivery(new_node)){ - if( new_res.Cost() + getBound_Bw( new_node, new_res.Time()) > 0 ){ - if( newLabelIdFw == new_label->Id() ){ - cout << "Label " << newLabelIdFw << " weggeboundet" << endl; + REF* ref = v_path_to_check[i]; + if (ref == label->generator_REF()) + { + int ii = i-1; + const t_labelFW* l = label->predecessor(); + while (ii >= 0 && label && label->generator_REF()) + { + if (v_path_to_check[ii] != l->generator_REF()) + return false; + ii--; + l = l->predecessor(); + } + label->b_check_required = (ii == -1 && l->generator_REF() == nullptr); + if (b_check_verbose && label->b_check_required) + { + cout << "### FW label Id=" << label->Id() << " of partial path ( s"; + vector<int> vertices; + const t_labelFW* l = label; + while (l->generator_REF()) + { + vertices.insert(vertices.begin(), l->generator_REF()->Head()); + l = l->predecessor(); } - delete new_label; - continue; + for (auto v : vertices) + cout << ", " << v; + cout << " ) created"; + if (label->predecessor()) + cout << " from pred_Id=" << label->predecessor()->Id(); + cout << ".\n"; } - }*/ - o_bucket_manager_fw.insert( new_label ); - v_dominance_manager_fw[new_node].insert( new_label ); + return label->b_check_required; + } } } - p_label->setIsExtended(); - // dominance can be delayed to any point in time, the bucket manager decides when - if ( o_bucket_manager_fw.invoke_dominance_algorithm() ) - { - apply_dominance_FW_TakeCare(newLabelIdFw); - } } - // final dominance - apply_dominance_FW_TakeCare(newLabelIdFw); + else + { + label->b_check_required = true; + if (b_check_verbose) + cout << "### Initial FW label Id=" << label->Id() << " is created. \n"; + return true; + } + return false; } -template <class REF, class BManagerFW, class DManagerFW, class BManagerBW, class DManagerBW, class MManager> -void c_SPPRC_Solver<REF, BManagerFW, DManagerFW, BManagerBW, DManagerBW, MManager> - ::SolveBidir_DynamicHalfway( MManager& merger, int source, int sink, ResVectFW&& init_res_fw, ResVectBW&& init_res_bw, const vector<int>& expectedTour, int maxnumpaths ) // not generic! +template<class REF, class ExtManagerFW, class DManagerFW, class ExtManagerBW, class DManagerBW, class MManager, class StatManager> +inline bool c_SPPRC_Solver<REF, ExtManagerFW, DManagerFW, ExtManagerBW, DManagerBW, MManager, StatManager>::CheckNewLabelBW(t_labelBW * label) { - c_TimeInfo timer_Solver; - timer_Solver.Start(); - o_timer_dyn_bidir_labeling.Start(); - ClearFW(); - ClearBW(); - p_merge_manager = &merger; - // init FW - int id_fw = 0; - t_labelFW* p_label_fw = new t_labelFW( id_fw++, std::move(init_res_fw), NULL, NULL ); - o_bucket_manager_fw.insert( p_label_fw ); - v_dominance_manager_fw[source].insert( p_label_fw ); - ResVectFW new_res_fw; - // init BW - int id_bw = 0; - t_labelBW* p_label_bw = new t_labelBW( id_bw++, std::move(init_res_bw), NULL, NULL ); - o_bucket_manager_bw.insert( p_label_bw ); - v_dominance_manager_bw[sink].insert( p_label_bw ); - ResVectBW new_res_bw; - // the dynamic part - p_merge_manager->SetHalfwayPointFW( (*p_label_bw)() ); - p_merge_manager->SetHalfwayPointBW( (*p_label_fw)() ); - p_label_fw = o_bucket_manager_fw.get_next(); - p_label_bw = o_bucket_manager_bw.get_next(); - bool forward = true; - - int predId = 0; - int newLabelIdFw = -1; - int newLabelIdBw = -1; - while ( ( p_label_fw || p_label_bw ) && ( v_dominance_manager_fw[sink].size()<maxnumpaths || v_dominance_manager_bw[source].size()<maxnumpaths ) ) - //while ( p_label_fw || p_label_bw ) + if (label->generator_REF()) { - if ( forward ) + if (label->predecessor()->b_check_required) { - if ( p_merge_manager->BeforeHalfWayPointFW( *p_label_fw ) ) + for (int i=0; i<(int)v_path_to_check.size(); i++) { - const ResVectFW& curr_res( *p_label_fw ); - int node = ( p_label_fw->generator_REF() ? p_label_fw->generator_REF()->Head() : source ); - - bool onExpectedTour = false; - int nextNode = -1; - if(p_label_fw->generator_REF() && p_label_fw->containsRoute(expectedTour, nextNode)){ - //cout << "Tour reached until node " << node << endl; - onExpectedTour = true; - } - - if( p_label_fw->Id() == 669 && node == 47 ) - cout << "Achtung" << endl; - - // iterate over forward star of the node - int max_idx = (int)v_fw_star[node].size(); - for ( int idx=0; idx<max_idx; idx++ ) + REF* ref = v_path_to_check[i]; + if (ref == label->generator_REF()) { - REF* p_ref = v_fw_star[node][idx]; - if ( p_ref->PropagateFw( curr_res, new_res_fw ) ) + int ii = i + 1; + const t_labelBW* l = label->predecessor(); + while (ii < v_path_to_check.size() && label && label->generator_REF()) { - t_labelFW* new_label = new t_labelFW( id_fw++, std::move(new_res_fw), p_label_fw, p_ref ); - o_bucket_manager_fw.insert( new_label ); - int new_node = p_ref->Head(); - if( onExpectedTour && p_ref->Head() == nextNode && p_ref->Tail() == node){ - newLabelIdFw = new_label->Id(); - cout << "Extended to fw-label " << new_label->Id() << " of node " << new_node << endl; - /*cout << " with costs: " << new_label->Cost() << ", time: " << new_label->Time() - << ", ll: " << new_label->LorryLoad() << ", tl: " << new_label->TrailerLoad() << endl;*/ - } - v_dominance_manager_fw[new_node].insert( new_label ); + if (v_path_to_check[ii] != l->generator_REF()) + return false; + ii++; + l = l->predecessor(); } - } - p_label_fw->setIsExtended(); - } - // dominance can be delayed to any point in time, the bucket manager decides when - if ( o_bucket_manager_fw.invoke_dominance_algorithm() ) - apply_dominance_FW_TakeCare(newLabelIdFw); - p_merge_manager->SetHalfwayPointBW( min( (*p_label_fw)(), p_merge_manager->HalfwayPointFW() ) ); - p_label_fw = o_bucket_manager_fw.get_next(); - } - else - { // backward - if ( p_merge_manager->BeforeHalfWayPointBW( *p_label_bw ) ) - { - const ResVectBW& curr_res( *p_label_bw ); - int node = ( p_label_bw->generator_REF() ? p_label_bw->generator_REF()->Tail() : sink ); - - bool onExpectedTour = false; - int nextNode = -1; - if(p_label_bw->generator_REF() && p_label_bw->containsRoute(expectedTour, nextNode)){ - //cout << "Tour reached until node " << node << endl; - onExpectedTour = true; - } - // iterate over backward star of the node - int max_idx = (int)v_bw_star[node].size(); - for ( int idx=0; idx<max_idx; idx++ ) - { - REF* p_ref = v_bw_star[node][idx]; - if ( p_ref->PropagateBw( curr_res, new_res_bw ) ) + label->b_check_required = (ii == v_path_to_check.size() && l->generator_REF() == nullptr); + if (b_check_verbose && label->b_check_required) { - t_labelBW* new_label = new t_labelBW( id_bw++, std::move(new_res_bw), p_label_bw, p_ref ); - o_bucket_manager_bw.insert( new_label ); - int new_node = p_ref->Tail(); - if( onExpectedTour && p_ref->Tail() == nextNode && p_ref->Head() == node){ - newLabelIdBw = new_label->Id(); - cout << "Extended to bw-label " << new_label->Id() << " of node " << new_node << endl; - /*cout << " with costs: " << new_label->Cost() << ", time: " << new_label->Time() - << ", ll: " << new_label->LorryLoad() << ", tl: " << new_label->TrailerLoad() << endl;*/ + cout << "### BW label Id=" << label->Id() << " of partial path ( "; + const t_labelBW* l = label; + while (l->generator_REF()) + { + cout << l->generator_REF()->Tail()<< ", "; + l = l->predecessor(); } - v_dominance_manager_bw[new_node].insert( new_label ); + cout << "t ) created"; + if (label->predecessor()) + cout << " from pred_Id=" << label->predecessor()->Id(); + cout << ".\n"; } + return label->b_check_required; } - p_label_bw->setIsExtended(); } - // dominance can be delayed to any point in time, the bucket manager decides when - if ( o_bucket_manager_bw.invoke_dominance_algorithm() ) - apply_dominance_BW_TakeCare(newLabelIdBw); - p_merge_manager->SetHalfwayPointFW( max( (*p_label_bw)(), p_merge_manager->HalfwayPointBW() ) ); - p_label_bw = o_bucket_manager_bw.get_next(); } - // Decide on whether we go forward or backward - //cout << "NumOpen_Fw: " << o_bucket_manager_fw.OpenLabels() << ", NumOpen_Bw: " << o_bucket_manager_bw.OpenLabels() << ", HW_Fw: " << p_merge_manager->HalfwayPointFW() << ", HW_Bw: " << p_merge_manager->HalfwayPointBW() << endl; - forward = ( o_bucket_manager_fw.OpenLabels() < o_bucket_manager_bw.OpenLabels() ); - if ( forward && !p_label_fw ) - forward = false; - if ( !forward && !p_label_bw ) - forward = true; } - // final dominance - apply_dominance_FW_TakeCare(newLabelIdFw); - apply_dominance_BW_TakeCare(newLabelIdBw); - o_timer_dyn_bidir_labeling.Stop(); + else + { + label->b_check_required = true; + if (b_check_verbose) + cout << "### Initial BW label Id=" << label->Id() << " is created. \n"; + return true; + } + return false; +} + + +template<class REF, class ExtManagerFW, class DManagerFW, class ExtManagerBW, class DManagerBW, class MManager, class StatManager> +inline bool c_SPPRC_Solver<REF, ExtManagerFW, DManagerFW, ExtManagerBW, DManagerBW, MManager, StatManager>::CheckPath(const vector<REF*>& path, bool verbose) +{ + b_check_verbose = verbose; + // Check that the path is well defined, i.e., sequence of REFs describes a path + if (path.empty()) + { + b_check_path = false; + v_path_to_check.clear(); + return true; + } + int pred = path[0]->Tail(); + for (auto ref : path) + { + if (ref->Tail() != pred) + { + std::cerr << "### The given REFs don't represent a path. Error at REF for (" << ref->Tail() + << ", " << ref->Head() << ") \n"; + return false; + } + pred = ref->Head(); + } + b_check_path = true; + v_path_to_check = path; + return true; } #endif + }; -#endif // of ESPPRC_SOLVER_H \ No newline at end of file +#endif // of ESPPRC_SOLVER_H diff --git a/settings/settings.txt b/settings/settings.txt index fc064b2a76374878f8940190b60c04cb4201d4c6..45fb959dbfaa67dfe0ebc51a7b28faafe55de519 100644 --- a/settings/settings.txt +++ b/settings/settings.txt @@ -2,7 +2,7 @@ %%%%%%%%%%%%%%%%%%%%%%%%% PVRP specific %%%%%%%%%%%%%%%%%%%%%%%%% % NetworkOfTasks true -RestrictVerticesWithDominanceCheck true +RestrictVerticesWithDominanceCheck false %This is not working anymore NetworkOfScheduleParts false RegularVisits false MinimumTourDuration true