/*Header file of the PStep_Dominator class

Implementation can be found in PStep_Dominator.cpp

This class represents a dominance function for labels.

This file also includes derived classes of PStep_Dominator.

*/

#ifndef _PSTEP_DOMINATOR_H
#define _PSTEP_DOMINATOR_H

#include "Label.h"
#include "BiDirectionalLabels.h"
#include <vector>

//Class used to represent a dominance function, exclusively load and costs are checked.
class PStep_Dominator{
public:

	//Tolerance
	double Tolerance;

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

	//Basic constructor
	PStep_Dominator(double NewTolerance)
		:Tolerance(NewTolerance)
	{};

	//Dominance functions
	//------------------------------------------------------------------------------------

	//This function checks whether CurrentLabel dominates NextLabel, if so the output is true, otherwise false.
	//Exclusively load and costs are checked.
	virtual bool Dominate(const Label& CurrentLabel, const Label& NextLabel);
	
	//This function checks whether CurrentLabel dominates NextLabel, if so the output is true, otherwise false.
	//Exclusively load and costs are checked.
	virtual bool Dominate(const ForwardLabel& CurrentLabel, const ForwardLabel& NextLabel);
	
	//This function checks whether CurrentLabel dominates NextLabel, if so the output is true, otherwise false.
	//Exclusively load and costs are checked.
	virtual bool Dominate(const BackwardLabel& CurrentLabel, const BackwardLabel& NextLabel);

};

//Class used to represent a dominance function, exclusively load and reachability are checked.
class PStep_ReachabilityDominator : public PStep_Dominator{
public:

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

	//Basic constructor
	PStep_ReachabilityDominator(double NewTolerance)
		:PStep_Dominator(NewTolerance)
	{};

	//Dominance functions
	//------------------------------------------------------------------------------------

	//This function checks whether CurrentLabel dominates NextLabel, if so the output is true, otherwise false.
	//Exclusively load, costs and reachability are checked.
	virtual bool Dominate(const Label& CurrentLabel, const Label& NextLabel);

	//This function checks whether CurrentLabel dominates NextLabel, if so the output is true, otherwise false.
	//Exclusively load, costs and reachability are checked.
	virtual bool Dominate(const ForwardLabel& CurrentLabel, const ForwardLabel& NextLabel);

	//This function checks whether CurrentLabel dominates NextLabel, if so the output is true, otherwise false.
	//Exclusively load, costs and reachability are checked.
	virtual bool Dominate(const BackwardLabel& CurrentLabel, const BackwardLabel& NextLabel);

};

//Class used to represent a dominance function, exclusively load is checked.
class PStep_LoadDominator : public PStep_Dominator{
public:

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

	//Basic constructor
	PStep_LoadDominator(double NewTolerance)
		:PStep_Dominator(NewTolerance)
	{};

	//Dominance functions
	//------------------------------------------------------------------------------------

	//This function checks whether CurrentLabel dominates NextLabel, if so the output is true, otherwise false.
	//Exclusively load is checked.
	virtual bool Dominate(const Label& CurrentLabel, const Label& NextLabel);
	virtual bool Dominate(const ForwardLabel& CurrentLabel, const ForwardLabel& NextLabel);
	virtual bool Dominate(const BackwardLabel& CurrentLabel, const BackwardLabel& NextLabel);

};

//Class used to represent a dominance function that always returns true.
class PStep_TrueDominator : public PStep_Dominator{
public:

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

	//Basic constructor
	PStep_TrueDominator(double NewTolerance)
		:PStep_Dominator(NewTolerance)
	{};

	//Dominance functions
	//------------------------------------------------------------------------------------

	//This function checks whether CurrentLabel dominates NextLabel, it always returns true.
	virtual bool Dominate(const Label& CurrentLabel, const Label& NextLabel){ return true; };

};

//Class used to represent a dominance function, exclusively reachability are checked.
class PStep_ReachabilityOnlyDominator : public PStep_Dominator{
public:

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

	//Basic constructor
	PStep_ReachabilityOnlyDominator(double NewTolerance)
		:PStep_Dominator(NewTolerance)
	{};

	//Dominance functions
	//------------------------------------------------------------------------------------

	//This function checks whether CurrentLabel dominates NextLabel, if so the output is true, otherwise false.
	//Exclusively reachability is checked.
	virtual bool Dominate(const Label& CurrentLabel, const Label& NextLabel);

};

//Class used to represent a dominance function when Ng-path relaxation is applied,
//exclusively load and reachability are checked.
class PStep_NGReachabilityDominator : public PStep_ReachabilityDominator{
public:

	//Neighbourhoods
	//Neighbourhoods.at(i).at(j) represents neighbour j of customer i (0 is the first customer).
	std::vector<std::vector<short int >>& Neighbourhoods;

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

	//Basic constructor
	PStep_NGReachabilityDominator(double NewTolerance, std::vector<std::vector<short int >>& NewNeighbourhoods)
		:PStep_ReachabilityDominator(NewTolerance), Neighbourhoods(NewNeighbourhoods)
	{};

	//Dominance functions
	//------------------------------------------------------------------------------------

	//This function checks whether CurrentLabel dominates NextLabel, if so the output is true, otherwise false.
	//Exclusively load, costs and reachability are checked.
	//Reachability is checked only for customers in the neighbourhood of CurrentLabel.LastLocation.
	//NOTE: This function CANNOT be applied if the CurrentLabel.LastLocation is the depot.
	virtual bool Dominate(const Label& CurrentLabel, const Label& NextLabel);

	//This function checks whether CurrentLabel dominates NextLabel, if so the output is true, otherwise false.
	//Exclusively load, costs and reachability are checked.
	//Reachability is checked only for customers in the neighbourhood of CurrentLabel.LastLocation.
	//NOTE: This function CANNOT be applied if the CurrentLabel.LastLocation is the depot.
	virtual bool Dominate(const ForwardLabel& CurrentLabel, const ForwardLabel& NextLabel);

	//This function checks whether CurrentLabel dominates NextLabel, if so the output is true, otherwise false.
	//Exclusively load, costs and reachability are checked.
	//Reachability is checked only for customers in the neighbourhood of CurrentLabel.LastLocation.
	//NOTE: This function CANNOT be applied if the CurrentLabel.LastLocation is the depot.
	virtual bool Dominate(const BackwardLabel& CurrentLabel, const BackwardLabel& NextLabel);

};

//Class used to represent a dominance function when Ng-path relaxation is applied,
//exclusively reachability is checked.
class PStep_NGReachabilityOnlyDominator : public PStep_NGReachabilityDominator{
public:

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

	//Basic constructor
	PStep_NGReachabilityOnlyDominator(double NewTolerance, std::vector<std::vector<short int >>& NewNeighbourhoods)
		:PStep_NGReachabilityDominator(NewTolerance,NewNeighbourhoods)
	{};

	//Dominance functions
	//------------------------------------------------------------------------------------

	//This function checks whether CurrentLabel dominates NextLabel, if so the output is true, otherwise false.
	//Exclusively reachability is checked.
	//Reachability is checked only for customers in the neighbourhood of CurrentLabel.LastLocation.
	//NOTE: This function CANNOT be applied if the CurrentLabel.LastLocation is the depot.
	virtual bool Dominate(const Label& CurrentLabel, const Label& NextLabel);

};

#endif