/* Solve the CVRP using a p-step formulation

Note:	the Lysgaard package allocates memory that is not freed.

Note:	PStep_Algorithm.h uses bitsets. The dimension of the bitset is defined by a constant.
		Therefore in the project properties / C/C++ / Preprocessor / Precompiler Definitions,
		the constant PSTEP_MAXLOCATIONS is introduced (in Debug and Release) to act as this
		dimension. As a result, no instances with more locations than PSTEP_MAXLOCATIONS
		can be solved. Locations is defined as the number of customers plus one depot.
*/

#include "PStep_Experiments.h"

int main(){
	
	//Experiment2();

	/*
	//Initialize settings
	CVRPInstanceGenerationSettings IGS(15, 50, 0, 10);
	//Generate instance
	CVRPInstance Instance(IGS);
	//Write instance to file:
	std::stringstream InstanceFileName;
	InstanceFileName << "C:\\Users\\Remy Spliet\\Documents\\Visual Studio 2019\\Instances\\CVRP Instances\\CVRPInstance.txt";
	Instance.Write(InstanceFileName.str().c_str());
	*/

	/*
	//Read instance file
	std::stringstream InstanceFileName;
	InstanceFileName << "C:\\Users\\Remy Spliet\\Documents\\Visual Studio 2019\\Instances\\CVRP Instances\\CVRPInstance.txt";
	CVRPInstance Instance(InstanceFileName.str().c_str());
	*/

	/*
	//Perform column generation:
	//Initialize settings
	PStep_AlgorithmSettings AlgorithmSettings(4, 3600, true, false);
	AlgorithmSettings.InitialPSteps = 3;
	AlgorithmSettings.UseNGPathRelaxation = false;
	AlgorithmSettings.NeighbourhoodSize = 0;
	AlgorithmSettings.ColumnGenerator = 21;
	AlgorithmSettings.SeparationStrategy = 0;
	AlgorithmSettings.PricingProblemSelection = 1;
	AlgorithmSettings.ColumnManager = 0;
	AlgorithmSettings.CMNumberOfColumnsLimit = 1000;
	AlgorithmSettings.CMThreshold = 5;
	//Initialize algorithm
	PStep_Algorithm Algorithm;
	//Solve LP relaxation
	Algorithm.SolveRootNode(Instance,AlgorithmSettings);
	//Write output to file:
	std::stringstream OutputFileName;
	OutputFileName << "C:\\Users\\Remy Spliet\\Documents\\Visual Studio 2019\\Projects\\P-step_CVRP\\Output\\CGStatistics.txt";
	Algorithm.AlgorithmMembers.CurrentCGStatistics.Write(OutputFileName.str().c_str());
	*/

	/*
	//Perform column generation for multiple p:
	//Go over various p
	for (int p = 1; p < 7; ++p){
		//Initialize settings
		PStep_AlgorithmSettings AlgorithmSettings(p, 3600, false, false);
		AlgorithmSettings.InitialPSteps = 3;
		AlgorithmSettings.UseNGPathRelaxation = true;
		AlgorithmSettings.NeighbourhoodSize = 8;
		AlgorithmSettings.ColumnGenerator = 20;
		AlgorithmSettings.SeparationStrategy = 0;
		AlgorithmSettings.PricingProblemSelection = 1;
		AlgorithmSettings.ColumnManager = 2;
		AlgorithmSettings.CMThreshold = 10;
		//Initialize algorithm
		PStep_Algorithm Algorithm;
		//Solve LP relaxation
		Algorithm.SolveRootNode(Instance, AlgorithmSettings);
		std::cout << "p is " << p << ": LP " << Algorithm.AlgorithmMembers.CurrentCGStatistics.FinalValue << " - Time " << Algorithm.AlgorithmMembers.CurrentCGStatistics.TotalComputationTime << std::endl;
		//Write output to file:
		std::stringstream OutputFileName;
		OutputFileName << "C:\\Users\\Remy Spliet\\Documents\\Visual Studio 2019\\Projects\\P-step_CVRP\\Output\\CGStatistics_"<< p << ".txt" ;
		Algorithm.AlgorithmMembers.CurrentCGStatistics.Write(OutputFileName.str().c_str());
	}
	*/

	/*
	//Branch and Price test
	//Initialize settings
	PStep_AlgorithmSettings AlgorithmSettings(2, 3600, false, true);
	AlgorithmSettings.InitialPSteps = 3;
	AlgorithmSettings.UseNGPathRelaxation = true;
	AlgorithmSettings.NeighbourhoodSize = 8;
	AlgorithmSettings.ColumnGenerator = 21;
	AlgorithmSettings.SeparationStrategy = 8;
	AlgorithmSettings.BranchingStrategy = 2;
	AlgorithmSettings.AbsoluteOptGap = 1;
	AlgorithmSettings.PricingProblemSelection = 1;
	AlgorithmSettings.ColumnManager = 3;
	//Initialize algorithm
	PStep_Algorithm Algorithm;
	//Branch-and-Price(-and-cut)
	Algorithm.BranchPriceAndCut(Instance,AlgorithmSettings);
	//Write output to file:
	std::stringstream OutputFileName;
	OutputFileName << "C:\\Users\\Remy Spliet\\Documents\\Visual Studio 2019\\Projects\\P-step_CVRP\\Output\\BPCStatistics.txt";
	Algorithm.AlgorithmMembers.CurrentBPCStatistics.Write(OutputFileName.str().c_str());
	*/

	/*
	//Perform branch-and-price for multiple p:
	//Go over various p
	for (int p = 1; p < 4; ++p){
		//Initialize settings
		PStep_AlgorithmSettings AlgorithmSettings(p, 3600, false, false);
		AlgorithmSettings.InitialPSteps = 3;
		AlgorithmSettings.UseNGPathRelaxation = true;
		AlgorithmSettings.NeighbourhoodSize = 8;
		AlgorithmSettings.ColumnGenerator = 21;
		AlgorithmSettings.SeparationStrategy = 8;
		AlgorithmSettings.BranchingStrategy = 2;
		AlgorithmSettings.AbsoluteOptGap = 1;
		AlgorithmSettings.PricingProblemSelection = 2;
		AlgorithmSettings.ColumnManager = 3;
		//Initialize algorithm
		PStep_Algorithm Algorithm;
		//Branch-and-Price(-and-cut)
		Algorithm.BranchPriceAndCut(Instance, AlgorithmSettings);
		//std::cout << "p is " << p << ": Value " << Algorithm.AlgorithmMembers.CurrentBPCStatistics.IterationStatistics.back().UpperBound << " - Time " << Algorithm.AlgorithmMembers.CurrentBPCStatistics.TotalTime << std::endl;
		std::cout << "p is n+1: Value " << Algorithm.AlgorithmMembers.CurrentBPCStatistics.IterationStatistics.back().UpperBound << " - Time " << Algorithm.GetPotentialBranchPriceAndCutTime() << std::endl;
		//Write output to file:
		std::stringstream OutputFileName;
		OutputFileName << "C:\\Users\\Remy Spliet\\Documents\\Visual Studio 2019\\Projects\\P-step_CVRP\\Output\\BPCStatistics_" << p << ".txt";
		Algorithm.AlgorithmMembers.CurrentBPCStatistics.Write(OutputFileName.str().c_str());
	}
	{
		//Initialize settings
		PStep_AlgorithmSettings AlgorithmSettings(102, 3600, false, false);
		AlgorithmSettings.InitialPSteps = 3;
		AlgorithmSettings.UseNGPathRelaxation = true;
		AlgorithmSettings.NeighbourhoodSize = 8;
		AlgorithmSettings.ColumnGenerator = 21;
		AlgorithmSettings.SeparationStrategy = 8;
		AlgorithmSettings.BranchingStrategy = 2;
		AlgorithmSettings.AbsoluteOptGap = 1;
		AlgorithmSettings.PricingProblemSelection = 2;
		AlgorithmSettings.ColumnManager = 3;
		//Initialize algorithm
		PStep_Algorithm Algorithm;
		//Branch-and-Price(-and-cut)
		Algorithm.BranchPriceAndCut(Instance, AlgorithmSettings);
		//std::cout << "p is n+1: Value " << Algorithm.AlgorithmMembers.CurrentBPCStatistics.IterationStatistics.back().UpperBound << " - Time " << Algorithm.AlgorithmMembers.CurrentBPCStatistics.TotalTime << std::endl;
		std::cout << "p is n+1: Value " << Algorithm.AlgorithmMembers.CurrentBPCStatistics.IterationStatistics.back().UpperBound << " - Time " << Algorithm.GetPotentialBranchPriceAndCutTime() << std::endl;
		//Write output to file:
		std::stringstream OutputFileName;
		OutputFileName << "C:\\Users\\Remy Spliet\\Documents\\Visual Studio 2019\\Projects\\P-step_CVRP\\Output\\BPCStatistics_n+1.txt";
		Algorithm.AlgorithmMembers.CurrentBPCStatistics.Write(OutputFileName.str().c_str());
	}
	*/
	
	/*
	//Convert instances
	std::stringstream EFileName;
	EFileName << "C:\\Users\\Priscilla\\Remy\\Visual Studio 2013\\Projects\\P-Step_CVRP\\Project Output\\Test Instances\\E-n101-k8.vrp";
	std::stringstream OutputFileName;
	OutputFileName << "C:\\Users\\Priscilla\\Remy\\Visual Studio 2013\\Projects\\P-Step_CVRP\\Project Output\\Test Instances\\HomeMadeFormat_E-n101-k8.txt";
	CVRPInstance temp;
	temp.ConvertECoordinatesToCVRPInstance(EFileName.str().c_str(),OutputFileName.str().c_str(),8,0);
	*/

	/*
	//Convert a series of instances
	//Set up for reading the A instances.
	std::vector<int> N = { 32, 33, 33, 34, 36, 37, 37, 38, 39, 39, 44, 45, 45, 46, 48, 53, 54, 55, 60, 61, 62, 63, 63, 64, 65, 69, 80 };
	std::vector<int> K = { 5, 5, 6, 5, 5, 5, 6, 5, 5, 6, 6, 6, 7, 7, 7, 7, 7, 9, 9, 9, 8, 9, 10, 9, 9, 9, 10 };
	//Go over all A instances
	auto k = K.begin();
	for (auto n = N.begin(); n != N.end(); ++n){
		//Convert instance
		std::stringstream AFileName;
		AFileName << "C:\\Users\\Priscilla\\Remy\\Visual Studio 2013\\Projects\\P-Step_CVRP\\Project Output\\Test Instances\\A Instances\\A-n" << *n << "-k" << *k << ".vrp";
		std::stringstream OutputFileName;
		OutputFileName << "C:\\Users\\Priscilla\\Remy\\Visual Studio 2013\\Projects\\P-Step_CVRP\\Project Output\\Test Instances\\A Instances\\HomeMadeFormat_A-n" << *n << "-k" << *k << ".txt";
		CVRPInstance temp;
		//(Change first redundant info from 21 to 20 words in CVRPInstance.Convert...)
		temp.ConvertECoordinatesToCVRPInstance(AFileName.str().c_str(), OutputFileName.str().c_str(), *k, 0);
		//Update k
		++k;
	}
	*/
	
	
	//Experiment column generation with all E-instances:
	//Set up for reading the E instances.
	//std::vector<int> N = { 13, 22, 23, 30, 31, 33, 51, 76, 76, 76, 76, 101, 101 };
	std::vector<int> N = { 13, 22, 23, 30, 31, 33 };
	//std::vector<int> K = { 4, 4, 3, 3, 7, 4, 5, 7, 8, 10, 14, 8, 14 };
	std::vector<int> K = { 4, 4, 3, 3, 7, 4 };
	//Print column headers:
	//std::cout << "Instance\t  p=1\t  p=2" << std::endl;
	//Go over all E instances
	auto k = K.begin();
	for (auto n = N.begin(); n != N.end(); ++n){

		//Read instance
		std::stringstream InstanceFileName;
		InstanceFileName << "C:\\Users\\Remy Spliet\\Documents\\Visual Studio 2019\\Instances\\CVRP Instances\\HomeMadeFormat_E-n" << *n << "-k" << *k << ".txt";
		CVRPInstance Instance(InstanceFileName.str().c_str());

		//Print progress
		std::cout << "E-n" << *n << "-k" << *k;

		//Perform column generation for multiple p:
		std::vector<int> pValues = { 1, 2, 3, 4, 7, 10, 13, 16, 128 };
		//Go over various p
		//for (int p = 1; p < 7; ++p){
		for(auto Currentp=pValues.begin();Currentp != pValues.end();++Currentp){
			int p = *Currentp;
			//Initialize settings
			PStep_AlgorithmSettings AlgorithmSettings(p, 3600, false, false);
			AlgorithmSettings.InitialPSteps = 3; 
			AlgorithmSettings.UseNGPathRelaxation = false;
			AlgorithmSettings.NeighbourhoodSize = 8;
			AlgorithmSettings.ColumnGenerator = 21;
			AlgorithmSettings.SeparationStrategy = 0;
			AlgorithmSettings.PricingProblemSelection = 1;
			AlgorithmSettings.ColumnManager = 3;
			AlgorithmSettings.CMThreshold = 10;
			AlgorithmSettings.CMNumberOfColumnsLimit = 1000;
			AlgorithmSettings.UseAdjustedCapacity = false;
			//Initialize algorithm
			PStep_Algorithm Algorithm;
			//Solve LP relaxation
			Algorithm.SolveRootNode(Instance, AlgorithmSettings);
			//Print progress
			if (Algorithm.AlgorithmMembers.CurrentCGStatistics.Flag == 0){
				std::cout << " & " << Algorithm.AlgorithmMembers.CurrentCGStatistics.FinalValue;
				//std::cout << " & " << Algorithm.AlgorithmMembers.CurrentCGStatistics.TotalComputationTime;
				//std::cout << " & " << Algorithm.GetPotentialColumnGenerationTime();
				//std::cout << " & " << Algorithm.AlgorithmMembers.CurrentCGStatistics.TotalLPTime / Algorithm.AlgorithmMembers.CurrentCGStatistics.TotalPricingTime;
			}
			else{
				std::cout << " & -";
			}
		}
		//Do a final run
		/* {
			//Initialize settings
			PStep_AlgorithmSettings AlgorithmSettings(102, 3600, false, false);
			AlgorithmSettings.InitialPSteps = 3;
			AlgorithmSettings.UseNGPathRelaxation = true;
			AlgorithmSettings.NeighbourhoodSize = 8;
			AlgorithmSettings.ColumnGenerator = 21;
			AlgorithmSettings.SeparationStrategy = 8;
			AlgorithmSettings.PricingProblemSelection = 1;
			AlgorithmSettings.ColumnManager = 3;
			AlgorithmSettings.CMThreshold = 10;
			AlgorithmSettings.CMNumberOfColumnsLimit = 1000;
			//Initialize algorithm
			PStep_Algorithm Algorithm;
			//Solve LP relaxation
			Algorithm.SolveRootNode(Instance, AlgorithmSettings);
			//Print progress
			if (Algorithm.AlgorithmMembers.CurrentCGStatistics.Flag == 0){
				//std::cout << " & " << Algorithm.AlgorithmMembers.CurrentCGStatistics.FinalValue;
				std::cout << " & " << Algorithm.AlgorithmMembers.CurrentCGStatistics.TotalComputationTime;
				//std::cout << " & " << Algorithm.GetPotentialColumnGenerationTime();
				//std::cout << " & " << Algorithm.AlgorithmMembers.CurrentCGStatistics.TotalLPTime / Algorithm.AlgorithmMembers.CurrentCGStatistics.TotalPricingTime;
			}
			else{
				std::cout << " & -";
			}

		}*/
		std::cout << " \\\\";
		std::cout << std::endl;

		//Update k
		++k;

	}
	

	/*
	//Experiment branch-price-and-cut with all E-instances:
	//Set up for reading the E instances.
	//std::vector<int> N = { 13, 22, 23, 30, 31, 33, 51, 76, 76, 76, 76, 101, 101 };
	std::vector<int> N = { 13, 22, 23, 30, 31, 33 };
	//std::vector<int> K = { 4, 4, 3, 3, 7, 4, 5, 7, 8, 10, 14, 8, 14 };
	std::vector<int> K = { 4, 4, 3, 3, 7, 4 };
	//Print column headers:
	//std::cout << "Instance\t  p=1\t  p=2" << std::endl;
	//Go over all E instances
	auto k = K.begin();
	for (auto n = N.begin(); n != N.end(); ++n){

		//Read instance
		std::stringstream InstanceFileName;
		InstanceFileName << "C:\\Users\\Remy Spliet\\Documents\\Visual Studio 2019\\Instances\\CVRP Instances\\HomeMadeFormat_E-n" << *n << "-k" << *k << ".txt";
		CVRPInstance Instance(InstanceFileName.str().c_str());

		//Print progress
		std::cout << "E-n" << *n << "-k" << *k;

		//Perform branch-and-price for multiple p:
		//Go over various p
		for (int p = 1; p < 5; ++p){
			//Initialize settings
			PStep_AlgorithmSettings AlgorithmSettings(p, 3600, false, false);
			AlgorithmSettings.UseNGPathRelaxation = true;
			AlgorithmSettings.NeighbourhoodSize = 8;
			AlgorithmSettings.ColumnGenerator = 20;
			AlgorithmSettings.SeparationStrategy = 8;
			AlgorithmSettings.BranchingStrategy = 2;
			AlgorithmSettings.AbsoluteOptGap = 1;
			AlgorithmSettings.PricingProblemSelection = 2;
			AlgorithmSettings.ColumnManager = 2;
			//Initialize algorithm
			PStep_Algorithm Algorithm;
			//Solve the problem
			Algorithm.BranchPriceAndCut(Instance, AlgorithmSettings);
			//Print progress
			if (Algorithm.AlgorithmMembers.CurrentBPCStatistics.Flag == 0){
				//std::cout << " & " << Algorithm.AlgorithmMembers.CurrentBPCStatistics.Solution.SolutionValue;
				//std::cout << " & " << Algorithm.AlgorithmMembers.CurrentBPCStatistics.TotalTime;
				std::cout << " & " << Algorithm.GetPotentialBranchPriceAndCutTime();
			}
			else{
				std::cout << " & -";
			}
		}
		//Do a final run
		{
			//Initialize settings
			PStep_AlgorithmSettings AlgorithmSettings(102, 3600, false, false);
			AlgorithmSettings.UseNGPathRelaxation = true;
			AlgorithmSettings.NeighbourhoodSize = 8;
			AlgorithmSettings.ColumnGenerator = 20;
			AlgorithmSettings.SeparationStrategy = 8;
			AlgorithmSettings.BranchingStrategy = 2;
			AlgorithmSettings.AbsoluteOptGap = 1;
			AlgorithmSettings.PricingProblemSelection = 2;
			AlgorithmSettings.ColumnManager = 2;
			//Initialize algorithm
			PStep_Algorithm Algorithm;
			//Solve the problem
			Algorithm.BranchPriceAndCut(Instance, AlgorithmSettings);
			//Print progress
			if (Algorithm.AlgorithmMembers.CurrentBPCStatistics.Flag == 0){
				//std::cout << " & " << Algorithm.AlgorithmMembers.CurrentBPCStatistics.Solution.SolutionValue;
				//std::cout << " & " << Algorithm.AlgorithmMembers.CurrentBPCStatistics.TotalTime;
				std::cout << " & " << Algorithm.GetPotentialBranchPriceAndCutTime();
			}
			else{
				std::cout << " & -";
			}

		}
		std::cout << " \\\\";
		std::cout << std::endl;

		//Update k
		++k;

	}
	*/

	/*
	//Experiment with all A-instances:
	//Set up for reading the A instances.
	std::vector<int> N = { 32, 33, 33, 34, 36, 37, 37, 38, 39, 39, 44, 45, 45, 46, 48, 53, 54, 55, 60, 61, 62, 63, 63, 64, 65, 69, 80 };
	std::vector<int> K = { 5, 5, 6, 5, 5, 5, 6, 5, 5, 6, 6, 6, 7, 7, 7, 7, 7, 9, 9, 9, 8, 9, 10, 9, 9, 9, 10 };
	//Print column headers:
	//std::cout << "Instance\t  p=1\t  p=2" << std::endl;
	//Go over all A instances
	auto k = K.begin();
	for (auto n = N.begin(); n != N.end(); ++n){

		//Read instance
		std::stringstream InstanceFileName;
		InstanceFileName << "C:\\Users\\Remy Spliet\\Documents\\Visual Studio 2019\\Instances\\CVRP Instances\\HomeMadeFormat_A-n" << *n << "-k" << *k << ".txt";
		CVRPInstance Instance(InstanceFileName.str().c_str());

		//Print progress
		std::cout << "A-n" << *n << "-k" << *k;

		//Perform column generation for multiple p:
		//Go over various p
		for (int p = 1; p < 7; ++p){
			//Initialize settings
			PStep_AlgorithmSettings AlgorithmSettings(p, 3600, false, false);
			AlgorithmSettings.InitialPSteps = 3;
			AlgorithmSettings.UseNGPathRelaxation = true;
			AlgorithmSettings.NeighbourhoodSize = 8;
			AlgorithmSettings.ColumnGenerator = 20;
			AlgorithmSettings.SeparationStrategy = 0;
			AlgorithmSettings.PricingProblemSelection = 1;
			AlgorithmSettings.ColumnManager = 2;
			AlgorithmSettings.CMThreshold = 10;
			//Initialize algorithm
			PStep_Algorithm Algorithm;
			//Solve LP relaxation
			Algorithm.SolveRootNode(Instance, AlgorithmSettings);
			//Print progress
			if (Algorithm.AlgorithmMembers.CurrentCGStatistics.Flag == 0){
				//std::cout << " & " << Algorithm.AlgorithmMembers.CurrentCGStatistics.FinalValue;
				std::cout << " & " << Algorithm.AlgorithmMembers.CurrentCGStatistics.TotalComputationTime;
			}
			else{
				std::cout << " & -";
			}
		}
		//Do a final run
		{
			//Initialize settings
			PStep_AlgorithmSettings AlgorithmSettings(102, 3600, false, false);
			AlgorithmSettings.InitialPSteps = 3;
			AlgorithmSettings.UseNGPathRelaxation = true;
			AlgorithmSettings.NeighbourhoodSize = 8;
			AlgorithmSettings.ColumnGenerator = 20;
			AlgorithmSettings.SeparationStrategy = 0;
			AlgorithmSettings.PricingProblemSelection = 1;
			AlgorithmSettings.ColumnManager = 2;
			AlgorithmSettings.CMThreshold = 10;
			//Initialize algorithm
			PStep_Algorithm Algorithm;
			//Solve LP relaxation
			Algorithm.SolveRootNode(Instance, AlgorithmSettings);
			//Print progress
			if (Algorithm.AlgorithmMembers.CurrentCGStatistics.Flag == 0){
				//std::cout << " & " << Algorithm.AlgorithmMembers.CurrentCGStatistics.FinalValue;
				std::cout << " & " << Algorithm.AlgorithmMembers.CurrentCGStatistics.TotalComputationTime;
			}
			else{
				std::cout << " & -";
			}

		}
		std::cout << " \\\\";
		std::cout << std::endl;

		//Update k
		++k;

	}
	*/

	return 0;

}