/*****************************************************************//**
 * \file   Label.h
 * \brief  Represents a label in DynamicProgramming which translates a group with the pair of first objective cost and second objective cost.
 *
 * \author Matteo Petris
 * \date   February 2023
 *********************************************************************/
#ifndef LABEL_H
#define LABEL_H

#include "Header.h"
#include "Utils.h"

 /**
 *	\class Label.
  * \brief  Represents a label in the ad hoc DynamicProgramming which translates an exchange.
 */
class Label {

private:

	int vertexId;
	int length;
	double cost;
	int weight;
	vector<int> ngMemory;
	vector<int> sequence;
	vector<int> active_SSI;
	bool isExtended;

public:

	//CONSTRUCTORS (default, parametrized, copy)
	Label();
	Label(const int& vertexId, const int& length, const int& weight, const double& cost);
	Label(const Label& l);

	//DESTRUCTOR
	~Label();

	//OPERATORS OVERLOADING (assignment, equality, not equal to)
	Label& operator=(const Label& l);
	//it returns 0 if it is false L1<L2, 1 if L1<L2 and L1 does not dominates L2, 2 if L1<l2 and L1 dominates L2
	friend int operator < (const Label& l1, const Label& l2);
	//Definition of operator == for a pair of labels (L1,L2): 
	//it returns 0 if L1!=L2, 1 if L1==L2 with respect to cost and resources, 2 if L1==l2 with respect to every attribute
	friend int operator == (const Label& l1, const Label& l2);

	//dominance operators when non robust cuts are active: this dominates label? this is equal to label
	int dominates_non_robust(const Label& label, const vector<double>& non_robust_duals, const vector<int>& active_non_robust_cuts);
	int equal_non_robust(const Label& label, const vector<double>& non_robust_duals, const vector<int>& active_non_robust_cuts);

	//dominance operators relaxed
	int dominates_relaxed(const Label& label);
	int equal_relaxed(const Label& label);

	int dominates_relaxed_non_robust(const Label& label, const vector<double>& non_robust_duals, const vector<int>& active_non_robust_cuts);
	int equal_relaxed_non_robust(const Label& label, const vector<double>& non_robust_duals, const vector<int>& active_non_robust_cuts);

	//METHODS
	void buildSequence(const vector<int>& oldSequence);
	void buildNgMemory(const vector<int>& oldNgMemory, const vector<int>& ngSet, const int& word, const int& bitkey);
	void buildNgSetFullMemory(const vector<int>& oldNgMemory, const int& word, const int& bitkey);
	bool isVisited(const int& word, const int& bitkey) const;
	void addNonRobustDual(const double& dual, const int& multiplier, const int& gcd, const int& pos);
	int get_visits_number(const int& vertex_id) const;

	/*
	*		sort the labels by increasing reduced cost
	*/
	static bool sortByCost(const Label& lhs, const Label& rhs) {
		return lhs.cost < rhs.cost;
	}

	//GET METHODS
	const int& getVertexId() const;
	const int& getLength() const;
	const int& getWeight() const;
	const double& getCost() const;
	const vector<int>& getNgMemory() const;
	const vector<int>& getSequence() const;
	const vector<int>& getActive_SSI() const;
	const bool& getIsExtended() const;

	//SET METHODS
	void setIsExtended(const bool& res);
	void setSequence(const vector<int>& seq);
	void setNgMemory(const int& wordsNumber);
	void setActive_SSI(const int& number_SSI);
	void setActive_SSI(const vector<int>& active_SSI);

	/**
	*	\brief	Converts the vertex into a string containing information related to it.
	*	Useful to have the vertex in an output like a text file or console.
	*	\return converted_vertex : string
	*/
	const string toString() const;

};

#endif //LABEL_H
