/*Implementation of PStep_BranchPriceAndCutStatistics.h

It contains the member functions of PStep_BranchPriceAndCutStatistics.
*/

#include "PStep_BranchPriceAndCutStatistics.h"

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

//Default Constructor
PStep_BranchPriceAndCutStatistics::PStep_BranchPriceAndCutStatistics(){

	//Set default values
	Flag = 0;
	TimeSolutionFound = 0;
	NumberOfConstructedNodes = 1;
	NumberOfProcessedNodes = 0;
	NumberOfMostFractionalEdgeBranching = 0;
	NumberOfLysgaardBranching = 0;
	TotalTime = 0;
	NumberOfPStepsStart = 0;
	NumberOfPStepsEnd = 0;
	NumberOfCCStart = 0;
	NumberOfCCEnd = 0;
	NumberOf2EHStart = 0;
	NumberOf2EHEnd = 0;
	NumberOfSCombStart = 0;
	NumberOfSCombEnd = 0;
	NumberOfFCCStart = 0;
	NumberOfFCCEnd = 0;
	NumberOfHMCStart = 0;
	NumberOfHMCEnd = 0;
	LPValue = 0;
	LPTime = 0;
	RootNodeValue = 0;
	RootNodeTime = 0;

}

//Copy Constructor
PStep_BranchPriceAndCutStatistics::PStep_BranchPriceAndCutStatistics(const PStep_BranchPriceAndCutStatistics &OriginalPStep_BranchPriceAndCutStatistics){

	CopyEmptyAssumed(OriginalPStep_BranchPriceAndCutStatistics);

}

//Operator functions:
//------------------------------------------------------------------------------------

//Assignment operator
PStep_BranchPriceAndCutStatistics PStep_BranchPriceAndCutStatistics::operator =(const PStep_BranchPriceAndCutStatistics &OriginalPStep_BranchPriceAndCutStatistics){

	EmptyStatistics();
	CopyEmptyAssumed(OriginalPStep_BranchPriceAndCutStatistics);
	return *this;

}

//Destructor functions
//------------------------------------------------------------------------------------

//Default destructor
PStep_BranchPriceAndCutStatistics::~PStep_BranchPriceAndCutStatistics(){

	EmptyStatistics();

}

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

//Function to write the statistics to file. The format can be deduced from the implementation.
void PStep_BranchPriceAndCutStatistics::Write(const char *FileName){

	//Create and open file
	std::ofstream File(FileName);
	//Check whether the file could be opened
	if (!File){
		std::cout << "Cannot open file " << FileName << "." << std::endl;
		return;
	}

	//Write the type of termination
	File << "Termination:               " << Flag;
	if (Flag == 0){
		File << " Optimum_Found             " << std::endl;
	}
	else if (Flag == 1){
		File << " Problem_Infeasible        " << std::endl;
	}
	else if (Flag == 2){
		File << " Time_Limit_Exceeded       " << std::endl;
	}

	//Value
	if (Solution.PSteps.size()>0){
		File << "Integer_Solution_Found:    1" << std::endl;
		File << "UpperBound:                " << Solution.SolutionValue << std::endl;
		File << "LowerBound:                " << IterationStatistics.back().LowerBound << std::endl;
		File << "Optimality_Gap:            " << ((Solution.SolutionValue - IterationStatistics.back().LowerBound) / Solution.SolutionValue) << std::endl;
		File << "LP_Value:                  " << LPValue << std::endl;
		File << "RootNodeValue:             " << RootNodeValue << std::endl;
	}
	else{
		File << "Integer_Solution_Found:    0" << std::endl;
		File << "Value:                     no_solution_found" << std::endl;
		File << "UpperBound:                no_solution_found" << std::endl;
		File << "LowerBound:                no_solution_found" << std::endl;
		File << "Optimality_Gap:            no_solution_found" << std::endl;
		File << "LP_Value:                  no_solution_found" << std::endl;
		File << "RootNodeValue:             no_solution_found" << std::endl;
	}

	//Completion time
	File << "Total_Time:                " << TotalTime << std::endl;

	//Time of finding the best solution
	if (Solution.PSteps.size()>0){
		File << "Best_Solution_Time:        " << TimeSolutionFound << std::endl;
		File << "LP_Time:                   " << LPTime << std::endl;
		File << "RootNode_Time:             " << RootNodeTime << std::endl;
	}
	else{
		File << "Best_Solution_Time:        no_solution_found" << std::endl;
	}

	//Created and processed nodes
	File << "Number_Of_Nodes_Created:   " << NumberOfConstructedNodes << std::endl;
	File << "Number_Of_Nodes_Processed: " << NumberOfProcessedNodes << std::endl;

	//Type of branching decisions
	File << "Most_Frac_Edge_Branching:  " << NumberOfMostFractionalEdgeBranching << std::endl;
	File << "Lysgaard_Branching:        " << NumberOfLysgaardBranching << std::endl;

	//Routes
	File << "Initial_p-steps:           " << NumberOfPStepsStart << std::endl;
	File << "p-steps_At_Termination:    " << NumberOfPStepsEnd << std::endl;

	//Valid inequalities
	File << "Cuts:                      (Initial/Final)" << std::endl;
	File << "Capacity:                  " << NumberOfCCStart << " / " << NumberOfCCEnd << std::endl;
	File << "2_Edge_Hypotour:           " << NumberOf2EHStart << " / " << NumberOf2EHEnd << std::endl;
	File << "Strengthened_Comb:         " << NumberOfSCombStart << " / " << NumberOfSCombEnd << std::endl;
	File << "Framed_Capacity:           " << NumberOfFCCStart << " / " << NumberOfFCCEnd << std::endl;
	File << "Homogeneous_Multistar:     " << NumberOfHMCStart << " / " << NumberOfHMCEnd << std::endl;

	//Progress per iteration
	File << std::endl << "Iteration-LB-UB-Time:" << std::endl;
	int Iteration = 0;
	for (auto Statistics = IterationStatistics.begin(); Statistics!=IterationStatistics.end(); ++Statistics){
		File << Iteration++ << ": " << Statistics->LowerBound << " " << Statistics->UpperBound << " " << Statistics->Time << std::endl;
	}

	File.close();

}

//Auxiliary functions
//------------------------------------------------------------------------------------

//Empty all entries
void PStep_BranchPriceAndCutStatistics::EmptyStatistics(){

	//Set default values
	Flag = 0;
	IterationStatistics.clear();
	Solution.EmptySolution();
	TimeSolutionFound = 0;
	NumberOfConstructedNodes = 1;
	NumberOfProcessedNodes = 0;
	NumberOfMostFractionalEdgeBranching= 0;
	NumberOfLysgaardBranching = 0;
	TotalTime = 0;
	NumberOfPStepsStart = 0;
	NumberOfPStepsEnd = 0;
	NumberOfCCStart = 0;
	NumberOfCCEnd = 0;
	NumberOf2EHStart = 0;
	NumberOf2EHEnd = 0;
	NumberOfSCombStart = 0;
	NumberOfSCombEnd = 0;
	NumberOfFCCStart = 0;
	NumberOfFCCEnd = 0;
	NumberOfHMCStart = 0;
	NumberOfHMCEnd = 0;
	LPValue = 0;
	LPTime = 0;
	RootNodeValue = 0;
	RootNodeTime = 0;

}

//Copy all entries
//IMPORTANT: it is assumed that the current statistics are empty!
void PStep_BranchPriceAndCutStatistics::CopyEmptyAssumed(const PStep_BranchPriceAndCutStatistics &OriginalPStep_BranchPriceAndCutStatistics){

	//Copy
	Flag = OriginalPStep_BranchPriceAndCutStatistics.Flag;
	IterationStatistics = OriginalPStep_BranchPriceAndCutStatistics.IterationStatistics;
	Solution = OriginalPStep_BranchPriceAndCutStatistics.Solution;
	TimeSolutionFound = OriginalPStep_BranchPriceAndCutStatistics.TimeSolutionFound;
	NumberOfConstructedNodes = OriginalPStep_BranchPriceAndCutStatistics.NumberOfConstructedNodes;
	NumberOfProcessedNodes = OriginalPStep_BranchPriceAndCutStatistics.NumberOfProcessedNodes;
	NumberOfMostFractionalEdgeBranching = OriginalPStep_BranchPriceAndCutStatistics.NumberOfMostFractionalEdgeBranching;
	NumberOfLysgaardBranching = OriginalPStep_BranchPriceAndCutStatistics.NumberOfLysgaardBranching;
	TotalTime = OriginalPStep_BranchPriceAndCutStatistics.TotalTime;
	NumberOfPStepsStart = OriginalPStep_BranchPriceAndCutStatistics.NumberOfPStepsStart;
	NumberOfPStepsEnd = OriginalPStep_BranchPriceAndCutStatistics.NumberOfPStepsEnd;
	NumberOfCCStart = OriginalPStep_BranchPriceAndCutStatistics.NumberOfCCStart;
	NumberOfCCEnd = OriginalPStep_BranchPriceAndCutStatistics.NumberOfCCEnd;
	NumberOf2EHStart = OriginalPStep_BranchPriceAndCutStatistics.NumberOf2EHStart;
	NumberOf2EHEnd = OriginalPStep_BranchPriceAndCutStatistics.NumberOf2EHEnd;
	NumberOfSCombStart = OriginalPStep_BranchPriceAndCutStatistics.NumberOfSCombStart;
	NumberOfSCombEnd = OriginalPStep_BranchPriceAndCutStatistics.NumberOfSCombEnd;
	NumberOfFCCStart = OriginalPStep_BranchPriceAndCutStatistics.NumberOfFCCStart;
	NumberOfFCCEnd = OriginalPStep_BranchPriceAndCutStatistics.NumberOfFCCEnd;
	NumberOfHMCStart = OriginalPStep_BranchPriceAndCutStatistics.NumberOfHMCStart;
	NumberOfHMCEnd = OriginalPStep_BranchPriceAndCutStatistics.NumberOfHMCEnd;
	LPValue = OriginalPStep_BranchPriceAndCutStatistics.LPValue;
	LPTime = OriginalPStep_BranchPriceAndCutStatistics.LPTime;
	RootNodeValue = OriginalPStep_BranchPriceAndCutStatistics.RootNodeValue;
	RootNodeTime = OriginalPStep_BranchPriceAndCutStatistics.RootNodeTime;

}