/*Header file of the PStep_Extender class

Implementation can be found in PStep_Extender.cpp

This class represents a function for extending labels.

This file also includes derived classes of PStep_Extender.

*/

#ifndef _PSTEP_EXTENDER_H
#define _PSTEP_EXTENDER_H

#include "PStep_FinalLabel.h"
#include <list>
#include <forward_list>
#include "PStep_Arc.h"
#include "PStep_ReachabilitySetter.h"

//Class used to represent a function for extending labels.
class PStep_Extender{
public:
	//Pointer to demand
	//Demand[i] is the demand of customer i, i=0 is the first customer.
	const double* Demand;

	//Pointer to dual arc costs
	//ReducedArcCosts[PStep_Arc::StartNode][Pstep_Arc::EndNode] should correspond to the costs of PStep_Arc.
	double** ReducedArcCosts;

	//Constructor functions:
	//------------------------------------------------------------------------------------

	//Basic constructor
	PStep_Extender(double *NewDemand, double **NewReducedArcCosts)
		: Demand(NewDemand), ReducedArcCosts(NewReducedArcCosts)
	{};

	//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.
	virtual void Extend(Label& CurrentLabel, PStep_Arc& Arc, std::forward_list<Label>& Labels);

	//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.
	virtual void Extend(Label& CurrentLabel, PStep_Arc& Arc, std::list<Label>& Labels);

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

	//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.
	virtual void Extend(ForwardLabel& CurrentForwardLabel, PStep_Arc& Arc, std::list<ForwardLabel>& ForwardLabels);

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

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

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

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

	//This function is used to modify the capacity (plus tolerance) for extenders who have such a (sub)member.
	virtual void SetCapacityPlusTolerance(double NewCapacityPlusTolerance){};

};

//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

//Class used to represent a function for extending labels only if the resulting costs are negative.
//It is e.g. of use when extending to the sink node. Furthermore, it does not create Label::Reachable.
class PStep_FinalExtender : public PStep_Extender{
public:
	//Tolerance
	double Tolerance;

	//Basic constructor
	PStep_FinalExtender(double *NewDemand, double **NewReducedArcCosts, double NewTolerance)
		: PStep_Extender(NewDemand,NewReducedArcCosts), Tolerance(NewTolerance)
	{};

	//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.
	virtual void Extend(Label& CurrentLabel, PStep_Arc& Arc, std::forward_list<PStep_FinalLabel>& Labels);

};

//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

//Class used to represent a function for extending labels to the depot only if the resulting costs are positive.
//Furthermore, it does not create Label::Reachable. It creates a PStep_FinalLabel with starting load 0.
class PStep_ZeroLoadDepotFinalExtender : public PStep_FinalExtender{
public:

	//Basic constructor
	PStep_ZeroLoadDepotFinalExtender(double *NewDemand, double **NewReducedArcCosts, double NewTolerance)
		: PStep_FinalExtender(NewDemand, NewReducedArcCosts, NewTolerance)
	{};

	//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.
	virtual void Extend(Label& CurrentLabel, PStep_Arc& Arc, std::forward_list<PStep_FinalLabel>& FinalLabels);

};

//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

//Class used to represent a function for extending labels only if the resulting costs are positive.
//It is of use when extending to the sink node. Furthermore, it does not create Label::Reachable.
//It creates a PStep_FinalLabel with starting load 0.
class PStep_ZeroLoadFinalExtender : public PStep_ZeroLoadDepotFinalExtender{
public:

	//Basic constructor
	PStep_ZeroLoadFinalExtender(double *NewDemand, double **NewReducedArcCosts, double NewTolerance)
		: PStep_ZeroLoadDepotFinalExtender(NewDemand, NewReducedArcCosts, NewTolerance)
	{};

	//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 Extend(Label& CurrentLabel, PStep_Arc& Arc, std::forward_list<PStep_FinalLabel>& FinalLabels);

};

//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

//Class used to represent a function for extending labels to the depot only if the resulting costs are positive.
//Furthermore, it does not create Label::Reachable. it sets the starting load to the maximum starting load.
class PStep_MaxLoadDepotFinalExtender : public PStep_FinalExtender{
public:

	//Capacity of p-step
	//It is used to determine the maximum starting load. It should be set prior to the call to Extend.
	double Capacity;

	//Basic constructor
	PStep_MaxLoadDepotFinalExtender(double *NewDemand, double **NewReducedArcCosts, double NewTolerance, double NewCapacity)
		: PStep_FinalExtender(NewDemand, NewReducedArcCosts, NewTolerance), Capacity(NewCapacity)
	{};

	//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.
	virtual void Extend(Label& CurrentLabel, PStep_Arc& Arc, std::forward_list<PStep_FinalLabel>& FinalLabels);

};

//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

//Class used to represent a function for extending labels only if the resulting costs are positive.
//It is of use when extending to the sink node. 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.
class PStep_MaxLoadFinalExtender : public PStep_MaxLoadDepotFinalExtender{
public:

	//Basic constructor
	PStep_MaxLoadFinalExtender(double *NewDemand, double **NewReducedArcCosts, double NewTolerance, double Capacity)
	: PStep_MaxLoadDepotFinalExtender(NewDemand, NewReducedArcCosts, NewTolerance, Capacity)
	{};

	//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 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 Extend(Label& CurrentLabel, PStep_Arc& Arc, std::forward_list<PStep_FinalLabel>& FinalLabels);

};

//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

//Class used to represent a function for extending labels, based on costs, load and Label::Reachable.
class PStep_StandardExtender : public PStep_Extender{
public:
	//Reference to a ReachabilitySetter
	PStep_ReachabilitySetter& ReachabilitySetter;

	//Constructor functions
	//------------------------------------------------------------------------------------

	//Basic constructor
	PStep_StandardExtender(double *NewDemand, double **NewReducedArcCosts, PStep_ReachabilitySetter &NewReachabilitySetter)
		: PStep_Extender(NewDemand,NewReducedArcCosts), ReachabilitySetter(NewReachabilitySetter)
	{};

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

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

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

	//This extension function creates a new ForwardLabel which is stored in NewForwardLabel.
	void Extend(ForwardLabel& CurrentForwardLabel, PStep_Arc& Arc, ForwardLabel &NewForwardLabel);
	
	//This extension function creates a new backward label which is placed at the front of
	//the forward list pointed to by BackwardLabels.
	void Extend(BackwardLabel& CurrentBackwardLabel, PStep_Arc& Arc, std::list<BackwardLabel>& BackwardLabels);

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

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

	//This function is used to modify the capacity (plus tolerance) of the reachability setter.
	virtual void SetCapacityPlusTolerance(double NewCapacityPlusTolerance);

};


#endif