/*Implementation of PStep_Extender 

It contains the member functions of PStep_Extender and all derived classes

*/

#include "PStep_Extender.h"

//PStep_Extender:
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

//Extension functions:

//This extension function creates a new label which is placed at the front of
//the forward list pointed to by Labels. Furthermore it does not create Label::Reachable.
void PStep_Extender::Extend(Label& CurrentLabel, PStep_Arc& Arc , std::forward_list<Label>& Labels){

	//Obtain current location
	short int CurrentLocation = Arc.EndNode;

	//Create new label
	Labels.emplace_front();
	Label& NewLabel = Labels.front();

	//Update costs
	NewLabel.Cost = CurrentLabel.Cost+ReducedArcCosts[Arc.StartNode][CurrentLocation];

	//Update load
	NewLabel.Load = CurrentLabel.Load + Demand[CurrentLocation - 1];

	//Update Lastlocation
	NewLabel.LastLocation = CurrentLocation;

	//Update previous label 
	NewLabel.PreviousLabel = &CurrentLabel;

}

//This extension function creates a new label which is placed at the front of
//the list pointed to by Labels. Furthermore it does not create Label::Reachable.
void PStep_Extender::Extend(Label& CurrentLabel, PStep_Arc& Arc, std::list<Label>& Labels){

	//Obtain current location
	short int CurrentLocation = Arc.EndNode;

	//Create new label
	Labels.emplace_front();
	Label& NewLabel = Labels.front();

	//Update costs
	NewLabel.Cost = CurrentLabel.Cost + ReducedArcCosts[Arc.StartNode][CurrentLocation];

	//Update load
	NewLabel.Load = CurrentLabel.Load + Demand[CurrentLocation - 1];

	//Update Lastlocation
	NewLabel.LastLocation = CurrentLocation;

	//Update previous label 
	NewLabel.PreviousLabel = &CurrentLabel;

}

//This extension function creates a new label which is stored in NewLabel.
//Furthermore it does not create Label::Reachable.
void PStep_Extender::Extend(Label& CurrentLabel, PStep_Arc& Arc, Label &NewLabel){

	//Obtain current location
	short int CurrentLocation = Arc.EndNode;

	//Update costs
	NewLabel.Cost = CurrentLabel.Cost + ReducedArcCosts[Arc.StartNode][CurrentLocation];

	//Update load
	NewLabel.Load = CurrentLabel.Load + Demand[CurrentLocation - 1];

	//Update LastLocation
	NewLabel.LastLocation = CurrentLocation;

	//Update previous label 
	NewLabel.PreviousLabel = &CurrentLabel;

}

//This extension function creates a new forward label which is placed at the front of
//the forward list pointed to by ForwardLabels. Furthermore it does not create
//ForwardLabel::Reachable nor ForwardLabel::Visited.
void PStep_Extender::Extend(ForwardLabel& CurrentForwardLabel, PStep_Arc& Arc, std::list<ForwardLabel>& ForwardLabels){

	//Obtain current location
	short int CurrentLocation = Arc.EndNode;

	//Create new label
	ForwardLabels.emplace_front();
	ForwardLabel& NewForwardLabel = ForwardLabels.front();

	//Update costs
	NewForwardLabel.Cost = CurrentForwardLabel.Cost + ReducedArcCosts[Arc.StartNode][CurrentLocation];

	//Update load
	NewForwardLabel.Load = CurrentForwardLabel.Load + Demand[CurrentLocation - 1];

	//Update Lastlocation
	NewForwardLabel.LastLocation = CurrentLocation;

	//Update previous label 
	NewForwardLabel.PreviousLabel = &CurrentForwardLabel;

}

//This extension function creates a new ForwardLabel which is stored in NewForwardLabel.
//Furthermore it does not create ForwardLabel::Reachable nor ForwardLabel::Visited.
void PStep_Extender::Extend(ForwardLabel& CurrentForwardLabel, PStep_Arc& Arc, ForwardLabel &NewForwardLabel){

	//Obtain current location
	short int CurrentLocation = Arc.EndNode;

	//Update costs
	NewForwardLabel.Cost = CurrentForwardLabel.Cost + ReducedArcCosts[Arc.StartNode][CurrentLocation];

	//Update load
	NewForwardLabel.Load = CurrentForwardLabel.Load + Demand[CurrentLocation - 1];

	//Update LastLocation
	NewForwardLabel.LastLocation = CurrentLocation;

	//Update previous label 
	NewForwardLabel.PreviousLabel = &CurrentForwardLabel;

}

//This extension function creates a new Backward label which is placed at the front of
//the Backward list pointed to by BackwardLabels. Furthermore it does not create
//BackwardLabel::Reachable nor BackwardLabel::Visited.
void PStep_Extender::Extend(BackwardLabel& CurrentBackwardLabel, PStep_Arc& Arc, std::list<BackwardLabel>& BackwardLabels){

	//Obtain current location
	short int CurrentLocation = Arc.StartNode;

	//Create new label
	BackwardLabels.emplace_front();
	BackwardLabel& NewBackwardLabel = BackwardLabels.front();

	//Update costs
	NewBackwardLabel.Cost = CurrentBackwardLabel.Cost + ReducedArcCosts[CurrentLocation][Arc.EndNode];

	//Update load
	NewBackwardLabel.Load = CurrentBackwardLabel.Load + Demand[CurrentLocation - 1];

	//Update Lastlocation
	NewBackwardLabel.FirstLocation = CurrentLocation;

	//Update previous label 
	NewBackwardLabel.NextLabel = &CurrentBackwardLabel;

}

//This extension function creates a new BackLabel which is stored in NewBackwardLabel.
//Furthermore it does not create BackwardLabel::Reachable nor BackwardLabel::Visited.
void PStep_Extender::Extend(BackwardLabel& CurrentBackwardLabel, PStep_Arc& Arc, BackwardLabel &NewBackwardLabel){

	//Obtain current location
	short int CurrentLocation = Arc.StartNode;

	//Update costs
	NewBackwardLabel.Cost = CurrentBackwardLabel.Cost + ReducedArcCosts[CurrentLocation][Arc.EndNode];

	//Update load
	NewBackwardLabel.Load = CurrentBackwardLabel.Load + Demand[CurrentLocation - 1];

	//Update FirstLocation
	NewBackwardLabel.FirstLocation = CurrentLocation;

	//Update next label 
	NewBackwardLabel.NextLabel = &CurrentBackwardLabel;

}

//PStep_PosistiveCostExtender : PStep_Extender:
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

//Extension function:
//------------------------------------------------------------------------------------
//This extension function creates a new label which is placed at the front of
//the forward list pointed to by Labels, only if the resulting costs are negative.
//Furthermore it does not create Label::Reachable. 
void PStep_FinalExtender::Extend(Label& CurrentLabel, PStep_Arc& Arc, std::forward_list<PStep_FinalLabel>& Labels){

	//Obtain current location
	short int CurrentLocation = Arc.EndNode;

	//Compute new cost
	double NewCost = CurrentLabel.Cost + ReducedArcCosts[Arc.StartNode][CurrentLocation];

	//Check whether the costs are negative
	if (NewCost < -Tolerance){
		
		//Create new label
		Labels.emplace_front();
		PStep_FinalLabel& NewFinalLabel = Labels.front();
		Label& NewLabel = NewFinalLabel.FinalLabel;

		//Update costs
		NewLabel.Cost = NewCost;

		//Update load
		NewLabel.Load = CurrentLabel.Load + Demand[CurrentLocation - 1];

		//Update Lastlocation
		NewLabel.LastLocation = CurrentLocation;

		//Update previous label 
		NewLabel.PreviousLabel = &CurrentLabel;

		//Update starting load
		NewFinalLabel.StartingLoad = 0;

	}

}

//PStep_ZeroLoadDepotFinalExtender : PStep_PositiveCostExtender:
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

//Extension function:
//------------------------------------------------------------------------------------
//This extension function creates a new PStep_FinalLabel which is placed at the front of
//the forward list pointed to by FinalLabels, only if the resulting costs are negative.
//It extend CurrentLabel to the depot.
//Furthermore, it does not create Label::Reachable. It creates a PStep_FinalLabel with starting load 0.
void PStep_ZeroLoadDepotFinalExtender::Extend(Label& CurrentLabel, PStep_Arc& Arc, std::forward_list<PStep_FinalLabel>& FinalLabels){

	//Obtain current location
	short int CurrentLocation = Arc.EndNode;

	//Compute new cost
	double NewCost = CurrentLabel.Cost + ReducedArcCosts[Arc.StartNode][CurrentLocation];

	//Check whether the costs are negative
	if (NewCost < -Tolerance){

		//Create new label
		FinalLabels.emplace_front();
		Label& NewLabel = FinalLabels.front().FinalLabel;

		//Update costs
		NewLabel.Cost = NewCost;

		//Update load
		NewLabel.Load = CurrentLabel.Load;

		//Update previous label 
		NewLabel.PreviousLabel = &CurrentLabel;

		//Update Lastlocation
		NewLabel.LastLocation = 0;

		//Update starting load
		FinalLabels.front().StartingLoad = 0;

	}

}

//PStep_ZeroLoadFinalExtender : PStep_MaxLoadDepotFinalExtender:
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

//Extension function:
//------------------------------------------------------------------------------------
//This extension function creates a new PStep_FinalLabel which is placed at the front of
//the forward list pointed to by FinalLabels, only if the resulting costs are negative.
//Furthermore, it does not create Label::Reachable.
//It creates a PStep_FinalLabel with starting load 0.
void PStep_ZeroLoadFinalExtender::Extend(Label& CurrentLabel, PStep_Arc& Arc, std::forward_list<PStep_FinalLabel>& FinalLabels){

	//Obtain current location
	short int CurrentLocation = Arc.EndNode;

	//Compute new cost
	double NewCost = CurrentLabel.Cost + ReducedArcCosts[Arc.StartNode][CurrentLocation];

	//Check whether the costs are negative
	if (NewCost < -Tolerance){

		//Create new label
		FinalLabels.emplace_front();
		Label& NewLabel = FinalLabels.front().FinalLabel;

		//Update costs
		NewLabel.Cost = NewCost;

		//Update load
		NewLabel.Load = CurrentLabel.Load + Demand[CurrentLocation - 1];

		//Update previous label 
		NewLabel.PreviousLabel = &CurrentLabel;

		//Update Lastlocation
		NewLabel.LastLocation = CurrentLocation;

		//Update starting load
		FinalLabels.front().StartingLoad = 0;

	}

}


//PStep_MaxLoadDepotFinalExtender : PStep_PositiveCostExtender:
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

//Extension function:
//------------------------------------------------------------------------------------
//This extension function creates a new PStep_FinalLabel which is placed at the front of
//the forward list pointed to by Labels, only if the resulting costs are negative.
//Furthermore, it does not create Label::Reachable.
//It creates a PStep_FinalLabel with starting load set to its maximum.
//Capacity is used to determine the max load, it should be set to the right value
//prior to calling Extend.
void PStep_MaxLoadDepotFinalExtender::Extend(Label& CurrentLabel, PStep_Arc& Arc, std::forward_list<PStep_FinalLabel>& FinalLabels){

	//Obtain current location
	short int CurrentLocation = Arc.EndNode;

	//Compute new cost
	double NewCost = CurrentLabel.Cost + ReducedArcCosts[Arc.StartNode][CurrentLocation];

	//Check whether the costs are negative
	if (NewCost < -Tolerance){

		//Create new label
		FinalLabels.emplace_front();
		Label& NewLabel = FinalLabels.front().FinalLabel;

		//Update costs
		NewLabel.Cost = NewCost;

		//Update load
		NewLabel.Load = CurrentLabel.Load;

		//Update Lastlocation
		NewLabel.LastLocation = 0;

		//Update previous label 
		NewLabel.PreviousLabel = &CurrentLabel;

		//Update starting load
		FinalLabels.front().StartingLoad = Capacity - CurrentLabel.Load;

	}

}

//PStep_MaxLoadFinalExtender : PStep_MaxLoadDepotFinalExtender:
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

//Extension function:
//------------------------------------------------------------------------------------
//This extension function creates a new PStep_FinalLabel which is placed at the front of
//the forward list pointed to by Labels, only if the resulting costs are negative.
//Furthermore, it does not create Label::Reachable.
//It creates a PStep_FinalLabel with starting load set to its maximum.
//Capacity is used to determine the max load, it should be set to the right value
//prior to calling Extend.
void PStep_MaxLoadFinalExtender::Extend(Label& CurrentLabel, PStep_Arc& Arc, std::forward_list<PStep_FinalLabel>& FinalLabels){

	//Obtain current location
	short int CurrentLocation = Arc.EndNode;

	//Compute new cost
	double NewCost = CurrentLabel.Cost + ReducedArcCosts[Arc.StartNode][CurrentLocation];

	//Check whether the costs are negative
	if (NewCost < -Tolerance){

		//Create new label
		FinalLabels.emplace_front();
		Label& NewLabel = FinalLabels.front().FinalLabel;

		//Update costs
		NewLabel.Cost = NewCost;

		//Compute the load of the new label
		double NewLoad = CurrentLabel.Load + Demand[CurrentLocation - 1];
		//Update load
		NewLabel.Load = NewLoad;

		//Update Lastlocation
		NewLabel.LastLocation = CurrentLocation;

		//Update previous label 
		NewLabel.PreviousLabel = &CurrentLabel;

		//Update starting load
		FinalLabels.front().StartingLoad = Capacity - NewLoad;

	}

}

//PStep_StandardExtender:
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

//Extension functions:

//This extension function creates a new label which is placed at the front of
//the forward list pointed to by Labels.
void PStep_StandardExtender::Extend(Label& CurrentLabel, PStep_Arc& Arc, std::list<Label>& Labels){

	//Obtain current location
	short int CurrentLocation = Arc.EndNode;

	//Obtain next customer
	short int NextCustomer = CurrentLocation - 1;

	//Create new label
	Labels.emplace_front();
	Label& NewLabel = Labels.front();

	//Update costs
	NewLabel.Cost = CurrentLabel.Cost + ReducedArcCosts[Arc.StartNode][CurrentLocation];

	//Update load
	NewLabel.Load = CurrentLabel.Load + Demand[NextCustomer];

	//Update number of locations
	NewLabel.NumberOfCustomers = CurrentLabel.NumberOfCustomers;

	//Update location resources
	ReachabilitySetter.SetReachability(CurrentLabel, NewLabel, NextCustomer);

	//Update Lastlocation
	NewLabel.LastLocation = CurrentLocation;

	//Update previous label 
	NewLabel.PreviousLabel = &CurrentLabel;

}

//This extension function creates a new label which is stored in NewLabel.
void PStep_StandardExtender::Extend(Label& CurrentLabel, PStep_Arc& Arc, Label& NewLabel){

	//Obtain current location
	short int CurrentLocation = Arc.EndNode;

	//Obtain next customer
	short int NextCustomer = CurrentLocation - 1;

	//Update costs
	NewLabel.Cost = CurrentLabel.Cost + ReducedArcCosts[Arc.StartNode][CurrentLocation];

	//Update load
	NewLabel.Load = CurrentLabel.Load + Demand[NextCustomer];

	//Update number of locations
	NewLabel.NumberOfCustomers = CurrentLabel.NumberOfCustomers;

	//Update location resources
	ReachabilitySetter.SetReachability(CurrentLabel, NewLabel, NextCustomer);

	//Update Lastlocation
	NewLabel.LastLocation = CurrentLocation;

	//Update previous label 
	NewLabel.PreviousLabel = &CurrentLabel;

}

//This extension function creates a new forward label which is placed at the front of
//the forward list pointed to by ForwardLabels.
void PStep_StandardExtender::Extend(ForwardLabel& CurrentForwardLabel, PStep_Arc& Arc, std::list<ForwardLabel>& ForwardLabels){

	//Obtain current location
	short int CurrentLocation = Arc.EndNode;

	//Obtain next customer
	short int NextCustomer = CurrentLocation - 1;

	//Create new label
	ForwardLabels.emplace_front();
	ForwardLabel& NewForwardLabel = ForwardLabels.front();

	//Update costs
	NewForwardLabel.Cost = CurrentForwardLabel.Cost + ReducedArcCosts[Arc.StartNode][CurrentLocation];

	//Update load
	NewForwardLabel.Load = CurrentForwardLabel.Load + Demand[NextCustomer];

	//Update number of locations
	NewForwardLabel.NumberOfCustomers = CurrentForwardLabel.NumberOfCustomers;

	//Update location resources
	ReachabilitySetter.SetReachability(CurrentForwardLabel, NewForwardLabel, NextCustomer);

	//Update Lastlocation
	NewForwardLabel.LastLocation = CurrentLocation;

	//Update previous label 
	NewForwardLabel.PreviousLabel = &CurrentForwardLabel;

}

//This extension function creates a new ForwardLabel which is stored in NewForwardLabel.
void PStep_StandardExtender::Extend(ForwardLabel& CurrentForwardLabel, PStep_Arc& Arc, ForwardLabel &NewForwardLabel){

	//Obtain current location
	short int CurrentLocation = Arc.EndNode;

	//Obtain next customer
	short int NextCustomer = CurrentLocation - 1;

	//Update costs
	NewForwardLabel.Cost = CurrentForwardLabel.Cost + ReducedArcCosts[Arc.StartNode][CurrentLocation];

	//Update load
	NewForwardLabel.Load = CurrentForwardLabel.Load + Demand[NextCustomer];

	//Update number of locations
	NewForwardLabel.NumberOfCustomers = CurrentForwardLabel.NumberOfCustomers;

	//Update location resources
	ReachabilitySetter.SetReachability(CurrentForwardLabel, NewForwardLabel, NextCustomer);

	//Update Lastlocation
	NewForwardLabel.LastLocation = CurrentLocation;

	//Update previous label 
	NewForwardLabel.PreviousLabel = &CurrentForwardLabel;

}

//This extension function creates a new Backward label which is placed at the front of
//the Backward list pointed to by BackwardLabels.
void PStep_StandardExtender::Extend(BackwardLabel& CurrentBackwardLabel, PStep_Arc& Arc, std::list<BackwardLabel>& BackwardLabels){

	//Obtain current location
	short int CurrentLocation = Arc.StartNode;

	//Obtain next customer
	short int NextCustomer = CurrentLocation - 1;

	//Create new label
	BackwardLabels.emplace_front();
	BackwardLabel& NewBackwardLabel = BackwardLabels.front();

	//Update costs
	NewBackwardLabel.Cost = CurrentBackwardLabel.Cost + ReducedArcCosts[CurrentLocation][Arc.EndNode];

	//Update load
	NewBackwardLabel.Load = CurrentBackwardLabel.Load + Demand[NextCustomer];

	//Update number of locations
	NewBackwardLabel.NumberOfCustomers = CurrentBackwardLabel.NumberOfCustomers;

	//Update location resources
	ReachabilitySetter.SetReachability(CurrentBackwardLabel, NewBackwardLabel, NextCustomer);

	//Update Lastlocation
	NewBackwardLabel.FirstLocation = CurrentLocation;

	//Update previous label 
	NewBackwardLabel.NextLabel = &CurrentBackwardLabel;

}

//This extension function creates a new BackLabel which is stored in NewBackwardLabel.
void PStep_StandardExtender::Extend(BackwardLabel& CurrentBackwardLabel, PStep_Arc& Arc, BackwardLabel &NewBackwardLabel){

	//Obtain current location
	short int CurrentLocation = Arc.StartNode;

	//Obtain next customer
	short int NextCustomer = CurrentLocation - 1;

	//Update costs
	NewBackwardLabel.Cost = CurrentBackwardLabel.Cost + ReducedArcCosts[CurrentLocation][Arc.EndNode];

	//Update load
	NewBackwardLabel.Load = CurrentBackwardLabel.Load + Demand[NextCustomer];

	//Update number of locations
	NewBackwardLabel.NumberOfCustomers = CurrentBackwardLabel.NumberOfCustomers;

	//Update location resources
	ReachabilitySetter.SetReachability(CurrentBackwardLabel, NewBackwardLabel, NextCustomer);

	//Update FirstLocation
	NewBackwardLabel.FirstLocation = CurrentLocation;

	//Update next label 
	NewBackwardLabel.NextLabel = &CurrentBackwardLabel;

}

//Other functions:
//------------------------------------------------------------------------------------

//This function is used to modify the capacity (plus tolerance) of the reachability setter.
void PStep_StandardExtender::SetCapacityPlusTolerance(double NewCapacityPlusTolerance){
	ReachabilitySetter.CapacityPlusTolerance = NewCapacityPlusTolerance;
}