/*Header file of the PStep_Merger class

Implementation can be found in PStep_Merger.cpp

This class represents a function for merging labels.

This file also includes derived classes of PStep_Merger.

*/

#ifndef _PSTEP_MERGER_H
#define _PSTEP_MERGER_H

#include "PStep_MergeLabel.h"
#include <forward_list>
#include <list>

//Class used to represent a function for merging a forward and backward label only if
//the resulting load does not exceed the capacity and the labels do not have any Visited in common.
class PStep_Merger{
public:

	//Capacity
	double Capacity;
	double CapacityPlusTolerance;

	//List were merged labels are stored
	std::forward_list<PStep_MergeLabel> &MergeLabels;

	//The number of created merge labels
	int NumberOfMergeLabels;

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

	//Basic constructor
	PStep_Merger(double NewCapacity, double NewCapacityPlusTolerance, std::forward_list<PStep_MergeLabel> &NewMergeLabels)
		: Capacity(NewCapacity), CapacityPlusTolerance(NewCapacityPlusTolerance), MergeLabels(NewMergeLabels), NumberOfMergeLabels(0)
	{};

	//Merge functions
	//------------------------------------------------------------------------------------

	//This merge function checks whether the combined load of the forward and backward labels 
	//do not exceed capacity and whether there is no location visited by both labels.
	//If this is indeed not the case, a new PStep_MergLabel is created and added to the list MergeLabels.
	virtual void Merge(ForwardLabel &CurrentForwardLabel, BackwardLabel &CurrentBackwardLabel)=0;

	//Check whether the CurrentForwardLabel and CurrentBackwardLabel have visited the same locations.
	//This is accomplished by backtracking and forward tracking both labels.
	virtual bool CheckVisited(ForwardLabel &CurrentForwardLabel, BackwardLabel &CurrentBackwardLabel);

};

//Class used to represent a function for merging a forward and backward label only if
//the resulting load does not exceed the capacity and the labels do not have any Visited in common.
//It is used when elementary paths are considered.
//The starting load is set to 0.
class PStep_ZeroLoadMerger : public PStep_Merger{
public:

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

	//Basic constructor
	PStep_ZeroLoadMerger(double NewCapacity, double NewCapacityPlusTolerance, std::forward_list<PStep_MergeLabel> &NewMergeLabels)
		: PStep_Merger(NewCapacity, NewCapacityPlusTolerance, NewMergeLabels)
	{};

	//Merge functions
	//------------------------------------------------------------------------------------

	//This merge function checks whether the combined load of the forward and backward labels 
	//do not exceed capacity and whether there is no location visited by both labels.
	//If this is indeed not the case, a new PStep_MergLabel is created and added to the list MergeLabels.
	//The starting load is set to 0.
	virtual void Merge(ForwardLabel &CurrentForwardLabel, BackwardLabel &CurrentBackwardLabel);

};

//Class used to represent a function for merging a forward and backward label only if
//the resulting load does not exceed the capacity and the labels do not have any Visited in common.
//It is used when elementary paths are considered.
//The starting load is set to its maximum.
class PStep_MaxLoadMerger : public PStep_Merger{
public:

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

	//Basic constructor
	PStep_MaxLoadMerger(double NewCapacity, double NewCapacityPlusTolerance, std::forward_list<PStep_MergeLabel> &NewMergeLabels)
		: PStep_Merger(NewCapacity, NewCapacityPlusTolerance, NewMergeLabels)
	{};

	//Merge functions
	//------------------------------------------------------------------------------------

	//This merge function checks whether the combined load of the forward and backward labels 
	//do not exceed capacity and whether there is no location visited by both labels.
	//If this is indeed not the case, a new PStep_MergLabel is created and added to the list MergeLabels.
	//The starting load is set to its maximum.
	virtual void Merge(ForwardLabel &CurrentForwardLabel, BackwardLabel &CurrentBackwardLabel);

};

//Class used to represent a function for merging a forward and backward label only if
//the resulting load does not exceed the capacity and the labels do not have any Visited in common.
//It is used when ng paths are considered.
//The starting load is set to 0.
class PStep_NGZeroLoadMerger : public PStep_Merger{
public:

	//Not in neighborhood indicates whether a customer is not in the neighborhoud.
	//NotInNeighbourhood.[i][j]=true if customer j is not a neighbor of customer i (0 is the first customer).
	bool** (&NotInNeighbourhood);

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

	//Basic constructor
	PStep_NGZeroLoadMerger(double NewCapacity, double NewCapacityPlusTolerance, std::forward_list<PStep_MergeLabel> &NewMergeLabels, bool** (&NewNotInNeighbourhood))
		: PStep_Merger(NewCapacity, NewCapacityPlusTolerance, NewMergeLabels), NotInNeighbourhood(NewNotInNeighbourhood)
	{};

	//Merge functions
	//------------------------------------------------------------------------------------

	//This merge function checks whether the combined load of the forward and backward labels 
	//do not exceed capacity and whether there is no location visited by both labels.
	//If this is indeed not the case, a new PStep_MergLabel is created and added to the list MergeLabels.
	//The starting load is set to 0.
	virtual void Merge(ForwardLabel &CurrentForwardLabel, BackwardLabel &CurrentBackwardLabel);

	//Check whether the CurrentForwardLabel and CurrentBackwardLabel have visited the same locations,
	//in the ng sense. This is accomplished by backtracking and forward tracking both labels.
	virtual bool CheckVisited(ForwardLabel &CurrentForwardLabel, BackwardLabel &CurrentBackwardLabel);

};

//Class used to represent a function for merging a forward and backward label only if
//the resulting load does not exceed the capacity and the labels do not have any Visited in common.
//It is used when ng paths are considered.
//The starting load is set to its maximum.
class PStep_NGMaxLoadMerger : public PStep_NGZeroLoadMerger{
public:

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

	//Basic constructor
	PStep_NGMaxLoadMerger(double NewCapacity, double NewCapacityPlusTolerance, std::forward_list<PStep_MergeLabel> &NewMergeLabels, bool** (&NewNotInNeighbourhood))
		: PStep_NGZeroLoadMerger(NewCapacity, NewCapacityPlusTolerance, NewMergeLabels, NewNotInNeighbourhood)
	{};

	//Merge functions
	//------------------------------------------------------------------------------------

	//This merge function checks whether the combined load of the forward and backward labels 
	//do not exceed capacity and whether there is no location visited by both labels.
	//If this is indeed not the case, a new PStep_MergLabel is created and added to the list MergeLabels.
	//The starting load is set to its maximum.
	virtual void Merge(ForwardLabel &CurrentForwardLabel, BackwardLabel &CurrentBackwardLabel);

};

#endif;