/*Implementation of PStep_ColumnManager.h

It contains the member functions of PStep_ColumnManager3

*/

#include "PStep_ColumnManager.h"

//PStep_ColumnManager2:
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

//Remove functions
//------------------------------------------------------------------------------------

//Remove p-steps included in x from the formulation in PStepLP.
//All columns are sorted in terms of reduced costs and the CMNumberOfColumnsLimit
//columns with the lowest reduced costs are maintained. All other columns with
//positive reduced costs are removed.
//Only CurrentPSteps are considered from (and including) FirstCurrentPStep up to (and excluding) LastCurrentPStep.
//ReducedCosts[CurrentPStepsxIndex[i]] should correspond to CurrentPSteps[i] and x[CurrentPSteps[i]].
void PStep_ColumnManager3::Remove(std::list<std::list<PStep>::iterator>::iterator FirstCurrentPStep, std::list<std::list<PStep>::iterator>::iterator LastCurrentPStep, IloNumVarArray& x, IloNumArray& ReducedCosts, IloEnv& env){

	//Obtain CurrentPSteps, -xIndices, the ShortList and their counters, and tolerance.
	std::list<std::list<PStep>::iterator>& CurrentPSteps = AlgorithmMembers.CurrentPSteps;
	std::list<int>& CurrentPStepsxIndices = AlgorithmMembers.CurrentPStepsxIndices;
	int& NumberOfCurrentPSteps = AlgorithmMembers.NumberOfCurrentPSteps;
	std::list<std::list<PStep>::iterator>& PStepShortList = AlgorithmMembers.PStepShortList;
	int& NumberOfPStepsInShortList = AlgorithmMembers.NumberOfPStepsInShortList;
	double Tolerance = AlgorithmMembers.Tolerance;

	//Convert the list of p-steps to a multimap of PstepReducedCostPairs:
	//Initialize multimap of PstepReducedCostPairs
	std::multiset<PStepReducedCostTriple> SortedPSteps;
	//Initialize index
	auto CurrentPStepxIndex = CurrentPStepsxIndices.begin();
	//Initialize counter
	int Counter = 0;
	//Go over all p-steps to be considered
	for (auto CurrentPStep = FirstCurrentPStep; CurrentPStep != LastCurrentPStep; ++CurrentPStep){
		//Emplace new triple
		SortedPSteps.emplace(CurrentPStep, CurrentPStepxIndex, ReducedCosts[Counter]);
		//Update xIndex and counter
		++CurrentPStepxIndex;
		++Counter;
	}

	//Obtain the number of p-steps of the sorted p-steps that should be maintained
	//The sorted p-steps do not contain the newly generated p-steps, which we never remove.
	//We only keep (more or less) NumberOfColumnsLimit in total, and SortedNumberOfColumnsLimit compensates for
	//the newly generated p-steps.
	int SortedNumberOfColumnsLimit = NumberOfColumnsLimit + Counter - NumberOfCurrentPSteps;
	//Initialize array of x variables to delete
	IloNumVarArray Deletex(env);
	//Initialize the current p-step
	auto CurrentSortedPStep = SortedPSteps.begin();
	//Initialize end of SortedPSteps
	auto SortedPStepsEnd = SortedPSteps.end();
	//Reinitialize Counter
	Counter = 0;
	//Go over all current p-steps to find the first p-step that needs to be remved
	while (CurrentSortedPStep != SortedPStepsEnd && (Counter < SortedNumberOfColumnsLimit || CurrentSortedPStep->ReducedCosts <= Tolerance)){
		//Update counter
		++CurrentSortedPStep;
		++Counter;
	}
	//Go over the remaining sorted p-steps and remove them
	for (; CurrentSortedPStep != SortedPStepsEnd; ++CurrentSortedPStep){
		//Remove the current p-step from the formulation and place it on the shortlist:

		//Place the current p-step on the shortlist
		PStepShortList.push_back(*(CurrentSortedPStep->ThisPStep));
		++NumberOfPStepsInShortList;

		//Mark the p-step variable for removal from the formulation
		Deletex.add(x[*(CurrentSortedPStep->xIndex)]);

		//Remove the current p-step and x index from the lists.
		CurrentPSteps.erase(CurrentSortedPStep->ThisPStep);
		CurrentPStepxIndex = CurrentPStepsxIndices.erase(CurrentSortedPStep->xIndex);
		--NumberOfCurrentPSteps;

	}

	//Remove all marked p-step variables from the formulation
	Deletex.endElements();

}