/*Implementation of PStep_ReachabilitySetter

It contains the member functions of PStep_ReachabilitySetter and all derived classes

*/

#include "PStep_ReachabilitySetter.h"

//PStep_ReachabilitySetter:
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

//Reachability setter:
//------------------------------------------------------------------------------------
//This function will be called during extension, it is assumed that the
//load of the new label is already updated, but Reachability has not yet been initialized.
//This function sets reachability to true for all locations that were
//currently reachable, are not the CurrentCustomer and extending would not
//cause a capacity violation.
//The input CurrentCustomer=0 represents the first customer.
void PStep_ReachabilitySetter::SetReachability(const Label& PreviousLabel, Label& NewLabel, short int CurrentCustomer){

	//Obtain the number of customers
	short int NumberOfCustomers = NewLabel.NumberOfCustomers;

	//Initialize reachability
	NewLabel.Reachable = new bool[NumberOfCustomers];

	//Go over all customers
	for (short int i = 0; i < NumberOfCustomers; ++i){

		//Check reachability
		if (PreviousLabel.Reachable[i] && NewLabel.Load + Demand[i] <= CapacityPlusTolerance){
			NewLabel.Reachable[i] = true;
		}
		else{
			NewLabel.Reachable[i] = false;
		}

	}//end go over all customers

	//Set reachability of the current customer
	NewLabel.Reachable[CurrentCustomer] = false;

}

//This function will be called during extension, it is assumed that the
//load of the new ForwardLabel is already updated, but Reachability
//has not yet been initialized.
//This function sets reachability to true for all locations that were
//currently reachable, are not the CurrentCustomer and extending would not
//cause a capacity violation.
//The input CurrentCustomer=0 represents the first customer.
void PStep_ReachabilitySetter::SetReachability(const ForwardLabel &PreviousLabel, ForwardLabel &NewForwardLabel, short int CurrentCustomer){

	//Obtain the number of customers
	short int NumberOfCustomers = NewForwardLabel.NumberOfCustomers;

	//Go over all customers until CurrentCustomer
	short int i = 0;
	for (; i < CurrentCustomer; ++i){
		//Set reachability
		NewForwardLabel.Reachable[i] = PreviousLabel.Reachable[i] && (NewForwardLabel.Load + Demand[i] <= CapacityPlusTolerance);
	}//end go over all customers
	//Set Reachability and Visited of the CurrentCustomer
	NewForwardLabel.Reachable[CurrentCustomer] = false; 
	//Go over all customers until CurrentCustomer
	++i;
	for (; i < NumberOfCustomers; ++i){
		//Set reachability
		NewForwardLabel.Reachable[i] = PreviousLabel.Reachable[i] && (NewForwardLabel.Load + Demand[i] <= CapacityPlusTolerance);
	}//end go over all customers

}

//This function will be called during extension, it is assumed that the
//load of the new BackwardLabel is already updated, but Reachability
//has not yet been initialized.
//This function sets reachability to true for all locations that were
//currently reachable, are not the CurrentCustomer and extending would not
//cause a capacity violation.
//The input CurrentCustomer=0 represents the first customer.
void PStep_ReachabilitySetter::SetReachability(const BackwardLabel &NextLabel, BackwardLabel &NewBackwardLabel, short int CurrentCustomer){

	//Obtain the number of customers
	short int NumberOfCustomers = NewBackwardLabel.NumberOfCustomers;

	//Go over all customers until CurrentCustomer
	short int i = 0;
	for (; i < CurrentCustomer; ++i){
		//Set reachability
		NewBackwardLabel.Reachable[i] = NextLabel.Reachable[i] && (NewBackwardLabel.Load + Demand[i] <= CapacityPlusTolerance);
	}//end go over all customers
	//Set Reachability of the CurrentCustomer
	NewBackwardLabel.Reachable[CurrentCustomer]=false;
	//Go over all customers until CurrentCustomer
	++i;
	for (; i < NumberOfCustomers; ++i){
		//Set reachability
		NewBackwardLabel.Reachable[i] = NextLabel.Reachable[i] && (NewBackwardLabel.Load + Demand[i] <= CapacityPlusTolerance);
	}//end go over all customers
	

}

//PStep_NGReachabilitySetter:
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

//Reachability setter:
//------------------------------------------------------------------------------------
//This function will be called during extension, it is assumed that the
//load of the new label is already updated, but Reachability has not yet been initialized.
//This function sets reachability to false for the CurrentCustomer, all customers in the neighbourhood 
//that were currently not reachable or extension would cause a capacity violation,
//and all customer that for which extension would cause a capacity violation.
//The input CurrentCustomer=0 represents the first customer.
void PStep_NGReachabilitySetter::SetReachability(const Label& PreviousLabel, Label& NewLabel, short int CurrentCustomer){

	//Obtain the number of customers
	short int NumberOfCustomers = NewLabel.NumberOfCustomers;
	//Obtain NotInNeighbourhood of the current customers
	bool* (&CurrentNotInNeighbourhood) = NotInNeighbourhood[CurrentCustomer];

	//Initialize reachability
	NewLabel.Reachable = new bool[NumberOfCustomers];

	//Go over all customers
	for (short int i = 0; i < NumberOfCustomers; ++i){

		//Check reachability:
		if (!(CurrentNotInNeighbourhood[i] || PreviousLabel.Reachable[i]) || i == CurrentCustomer || NewLabel.Load + Demand[i] > CapacityPlusTolerance){
			NewLabel.Reachable[i] = false;
		}
		else{
			NewLabel.Reachable[i] = true;
		}

	}//end go over all customers

}

//This function will be called during extension, it is assumed that the
//load of the new ForwardLabel is already updated, but Reachability
//has not yet been initialized.
//This function sets reachability to false for the CurrentCustomer, all customers in the neighbourhood 
//that were currently not reachable or extension would cause a capacity violation,
//and all customer that for which extension would cause a capacity violation.
//The input CurrentCustomer=0 represents the first customer.
void PStep_NGReachabilitySetter::SetReachability(const ForwardLabel &PreviousLabel, ForwardLabel &NewForwardLabel, short int CurrentCustomer){

	//Obtain the number of customers
	short int NumberOfCustomers = NewForwardLabel.NumberOfCustomers;
	//Obtain NotInNeighbourhood of the current customers
	bool* (&CurrentNotInNeighbourhood) = NotInNeighbourhood[CurrentCustomer];

	//Initialize reachability
	std::bitset<PSTEP_MAXLOCATIONS> (&Reachable) = NewForwardLabel.Reachable;
	//Initialize reachability
	const std::bitset<PSTEP_MAXLOCATIONS> (&PreviousReachable) = PreviousLabel.Reachable;

	//Go over all customers until the current customer
	short int i = 0;
	for (; i < CurrentCustomer; ++i){
		//Check reachability:
		if (CurrentNotInNeighbourhood[i]){
			//Set reachability
			Reachable[i] = (NewForwardLabel.Load + Demand[i] <= CapacityPlusTolerance);
		}
		else{
			//Set reachability
			Reachable[i] = (PreviousReachable[i] && (NewForwardLabel.Load + Demand[i] <= CapacityPlusTolerance));
		}
	}//end go over all customers
	//Set Reachability and Visited of the CurrentCustomer
	Reachable[CurrentCustomer] = false;
	//Go over all customers from the currentcustomer
	++i;
	for (; i < NumberOfCustomers; ++i){
		//Check reachability:
		if (CurrentNotInNeighbourhood[i]){
			//Set reachability
			Reachable[i] = (NewForwardLabel.Load + Demand[i] <= CapacityPlusTolerance);
		}
		else{
			//Set reachability
			Reachable[i] = (PreviousReachable[i] && (NewForwardLabel.Load + Demand[i] <= CapacityPlusTolerance));
		}
	}//end go over all customers

}

//This function will be called during extension, it is assumed that the
//load of the new BackwardLabel is already updated, but Reachability
//has not yet been initialized.
//This function sets reachability to false for the CurrentCustomer, all customers in the neighbourhood 
//that were currently not reachable or extension would cause a capacity violation,
//and all customer that for which extension would cause a capacity violation.
//The input CurrentCustomer=0 represents the first customer.
void PStep_NGReachabilitySetter::SetReachability(const BackwardLabel &NextLabel, BackwardLabel &NewBackwardLabel, short int CurrentCustomer){

	//Obtain the number of customers
	short int NumberOfCustomers = NewBackwardLabel.NumberOfCustomers;
	//Obtain NotInNeighbourhood of the current customers
	bool* (&CurrentNotInNeighbourhood) = NotInNeighbourhood[CurrentCustomer];

	//Obtain reachability
	std::bitset<PSTEP_MAXLOCATIONS> (&Reachable) = NewBackwardLabel.Reachable;
	//Initialize reachability
	const std::bitset<PSTEP_MAXLOCATIONS>(&NextReachable) = NextLabel.Reachable;

	//Go over all customers until the current customer
	short int i = 0;
	for (; i < CurrentCustomer; ++i){
		//Check reachability:
		if (CurrentNotInNeighbourhood[i]){
			//Set reachability
			Reachable[i] = (NewBackwardLabel.Load + Demand[i] <= CapacityPlusTolerance);
		}
		else{
			//Set reachability
			Reachable[i] = (NextReachable[i] && NewBackwardLabel.Load + Demand[i] <= CapacityPlusTolerance);
		}
	}//end go over all customers
	//Set Reachability the CurrentCustomer
	Reachable[CurrentCustomer] = false;
	//Go over all customers from the currentcustomer
	++i;
	for (; i < NumberOfCustomers; ++i){
		//Check reachability:
		if (CurrentNotInNeighbourhood[i]){
			//Set reachability
			Reachable[i] = (NewBackwardLabel.Load + Demand[i] <= CapacityPlusTolerance);
		}
		else{
			//Set reachability
			Reachable[i] = (NextReachable[i] && NewBackwardLabel.Load + Demand[i] <= CapacityPlusTolerance);
		}
	}//end go over all customers

}