#ifndef _LCE_H
#define	_LCE_H

#define LCE_OK 0
#define LCE_ERROR -1

#include "common.h"
#include "lagrange.h"
#include "ei_simplex.h"



/** \defgroup LCE L-Class enumeration for SCP
 *  \brief L-Class enumeration solves ILP by converting ILP to sequence
 *   of specially formed LP's while examining integer parts of LP solutions
 *  @{*/

#ifdef	__cplusplus
extern "C" {
#endif

typedef struct _LCE LCE;

/** \brief Result of step 2 of L-Class enumeration*/
typedef enum {
    /** Integer L-Class found*/
    LCE_LM_FOUND_INTEGER_L_CLASS=0,
    /** Fractional L-Class found*/
    LCE_LM_FOUND_L_CLASS=1,
    /** Algorithm will be terminated*/
    LCE_LM_QUIT=2,
    /** No L-Class found*/
    LCE_LM_NOT_FOUND=3

} LCELexminResult;


/** \brief LCE*/
struct _LCE {
    
    /**\brief View to the underlying problem*/
    SCPView* problemView;
    
    /**\brief fi Index of last bound column*/
    int fi;
    /**\brief r So called record. Cost of cheapest integer L-Class ever found*/
    int r;
    /**\brief p Greatest index of column that has assigned one*/
    int p;
    
    /**\brief xd Vector that holds current L-Class*/
    double* xd;
    
    /**\brief xdd Vector that holds L-Class being probed*/
    double* xdd;

    /**\brief Indicates whether Lagrangean heuristic is used
     *  to accelerate L-class enumeration
     */
    int useLagrange;

    
    int stIterationCount;
    int stLexminLagrangeImproved;
    int stLexminRunCount;
    int stLexminNoFeasibleCount;
    int stGTHRunCount;
    int stGTHLagrangeImproved;
    int stGTHFeasibleCount;
    double stTotalCPUTime;

    /** What lagrangean heuristic type is used*/
    HeuristicType heuristicType;

    /** How many integer L-Classes with lower cost were found*/
    int stIntegerClassesFound;

    /** Stored best integer L-Class found*/
    double* lastIntegerLClass;

    /** Temporary row mask*/
    unsigned char* rowMask;

    /** Temporary column mask*/
    unsigned char* columnMask;
    
};

/*Functions*/

/**\brief Create new LCE
 * \param pv View to the problem that will be solved
 * \param type Type of lagrangean heuristic
 * \param useLagrange Indicates whether Lagrangean heuristic is used
 *  for acceleration of the LCE
 * \return LCE or NULL
 */
LCE* lce_new(SCPView* pv,HeuristicType type,int useLagrange);

/**\brief Solve the problem using LCE
 * \param initialRecord Initial record (found by some heuristic for example)
 */
 int lce_solve(LCE* lc,int initialRecord);
 
 
 /**\brief Get solution in form of mask of columns
  * \param retMask pointer to already allocated mask
  */
 void lce_get_solution(LCE* lc,unsigned char* retMask);

 /** \brief Perform the group testing heuristic
  *  \return Same result as lce_perform_step_2
  */
 LCELexminResult lce_group_testing_heurisitc(LCE* lc);

/** \brief Find initial lexicographicaly minimal integer L-Class*/
void lce_find_initial_lexmin(LCE* lc);

/** \brief Save new integer L-Class that recently improved the record*/
void lce_save_new_improving_integer_lclass(LCE* lc,double* mask);

/** \brief Perform step 2 of the LCE*/
LCELexminResult lce_perform_step_2(LCE* lc);

/** \brief Suplmenetary comparation function*/
int lce_compare(SCPView* v,int c1,int c2,void* miscData);

/** \brief Compare two L-classes lexicographically
 *  \return Result of comparation -1,0,1
 */
int lce_compare_lclasses_lex(LCE* lc,double* a,double* b);

 /**\brief Delete LCE*/
 void lce_delete(LCE* lc);

 /**\brief Print state of the LCE*/
 void lce_print(LCE* lc);

 /** \brief Calculate current cost of vector xd
  *  \return Cost of the vector xd
  */
 double lce_calculate_xd_cost(LCE* lc);


#ifdef	__cplusplus
}
#endif

#endif	/* _LCE_H */

/** @}*/

