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