
/*
**  This file forms part of the GOBLIN C++ Class Library.
**
**  Written by Christian Fremuth-Paeger, November 2002.
**  
**  Copying, compiling, distribution and modification
**  of this source code is permitted only in accordance
**  with the GOBLIN general licence information.
*/             


#if !defined(_ILPWRAPPER_H_)

#define _ILPWRAPPER_H_

#include "absobj.h"


//****************************************************************************//
//          General interface description for LP and MIP instances            //
//****************************************************************************//


class goblinILPWrapper : public virtual goblinDataObject
{
private:

    unsigned        bufferLength;
    char*           labelBuffer;

public:

    goblinILPWrapper() throw();
    virtual ~goblinILPWrapper() throw();

    unsigned long   Allocated() throw();

    bool            IsMixedILP() {return true;};


    // *************************************************************** //
    //                             File IO                             //
    // *************************************************************** //

    enum TDisplayOpt {
        DISPLAY_PROBLEM = 0,
        DISPLAY_OBJECTIVE = 1,
        DISPLAY_RESTRICTIONS = 2,
        DISPLAY_BOUNDS = 4,
        DISPLAY_INTEGERS = 8,
        DISPLAY_FIXED = 16,
        DISPLAY_PRIMAL = 32,
        DISPLAY_DUAL = 64,
        DISPLAY_SLACKS = 128,
        DISPLAY_BASIS = 256,
        DISPLAY_TABLEAU = 512,
        DISPLAY_INVERSE = 1024
    };

    enum TLPFormat
        {MPS_FORMAT=0,LP_FORMAT=1,MPS_CPLEX=2,BAS_CPLEX=3,BAS_GOBLIN=4};
    
    void    Write(const char*,TOption = 0)
                throw(ERFile,ERRejected);
    void    Write(const char*,TLPFormat,TOption = 0)
                throw(ERFile,ERRejected);
    void    WriteLPNaive(const char*,TDisplayOpt = DISPLAY_PROBLEM)
                throw(ERFile,ERRejected);
    void    WriteMPSFile(const char*,TLPFormat = MPS_CPLEX)
                throw(ERFile,ERRejected);
    void    WriteMPSFile(ofstream&,TLPFormat = MPS_CPLEX)
                throw(ERFile,ERRejected);
    void    WriteBASFile(const char*,TLPFormat = BAS_CPLEX)
                throw(ERFile,ERRejected);
    void    WriteBASFile(ofstream&,TLPFormat = BAS_CPLEX)
                throw(ERFile,ERRejected);
    char*   Display() throw(ERFile,ERRejected);

    void    Export2XFig(const char*) throw(ERFile,ERRejected)
                {throw ERRejected();};
    void    Export2Tk(const char*) throw(ERFile,ERRejected)
                {throw ERRejected();};
    void    Export2Ascii(const char* fileName,TOption opt=0) throw(ERFile)
                {WriteLPNaive(fileName,TDisplayOpt(opt));};

private:

    TVar    ReadRowLabel(char*) throw();
    TRestr  ReadColLabel(char*,bool) throw();

public:

    void    ReadMPSFile(const char*) throw(ERParse,ERRejected);
    void    ReadMPSFile(ifstream&) throw(ERParse,ERRejected);
    void    ReadBASFile(const char*) throw(ERParse,ERRejected);
    void    ReadBASFile(ifstream&) throw(ERParse,ERRejected);

    void    NoSuchVar(char*,TVar) throw(ERRange);
    void    NoSuchRestr(char*,TRestr) throw(ERRange);

    
    // *************************************************************** //
    //                      Instance Manipulation                      //
    // *************************************************************** //

    enum TVarType
        {VAR_FLOAT=0,VAR_INT=1,VAR_CANCELED=2};

    virtual TVar    AddVar(TFloat,TFloat,TFloat,TVarType = VAR_FLOAT)
                        throw(ERRejected) = 0;
    virtual TRestr  AddRestr(TFloat,TFloat) throw(ERRejected) = 0;

    virtual void    DeleteVar(TVar) throw(ERRange,ERRejected) = 0;
    virtual void    DeleteRestr(TRestr) throw(ERRange) = 0;

    virtual void    SetURange(TVar,TFloat) throw(ERRange) = 0;
    virtual void    SetLRange(TVar,TFloat) throw(ERRange) = 0;
    virtual void    SetUBound(TRestr,TFloat) throw(ERRange) = 0;
    virtual void    SetLBound(TRestr,TFloat) throw(ERRange) = 0;
    virtual void    SetCost(TVar,TFloat) throw(ERRange) = 0;
    virtual void    SetVarType(TVar,TVarType) throw(ERRange) = 0;

    virtual void    SetVarLabel(TVar,char*,TOwnership = OWNED_BY_SENDER)
                        throw(ERRange,ERRejected) = 0;
    virtual void    SetRestrLabel(TRestr,char*,TOwnership = OWNED_BY_SENDER)
                        throw(ERRange,ERRejected) = 0;

    enum TDirection
        {MAXIMIZE=2,NO_OBJECTIVE=0,MINIMIZE=1};

    virtual void    SetDirection(TDirection) throw() = 0;

    virtual void    SetCoeff(TRestr,TVar,TFloat) throw(ERRange) = 0;

    virtual void    SetRow(TRestr i,TVar len,TVar* index,double* val)
                        throw(ERRange) = 0;
	// Sets row i of the coefficient matrix. len is the number
	// of nonzeros in the new row i. The coefficients are given by
	// index and val.

	virtual void    SetColumn(TVar j,TRestr len,TRestr* index,double* val)
                        throw(ERRange) = 0;
	// Sets columns j of the coefficient matrix. len is the
	// number of nonzeros in the new column j. The coefficients
	// are given by index and val.

    virtual void    SetVarVisibility(TVar,bool) throw(ERRange) {};
    virtual void    SetRestrVisibility(TRestr,bool) throw(ERRange) {};

    virtual void    Resize(TRestr,TVar,TIndex) throw(ERRange) = 0;
    virtual void    Strip() throw() = 0;

    
    // *************************************************************** //
    //                      Retrieval Operations                       //
    // *************************************************************** //
    
    virtual TRestr  K() throw() = 0;
    virtual TVar    L() throw() = 0;
    virtual TIndex  NZ() throw() = 0;
    
    virtual TFloat  Cost(TVar) throw(ERRange) = 0;
    virtual TFloat  URange(TVar) throw(ERRange) = 0;
    virtual TFloat  LRange(TVar) throw(ERRange) = 0;
    virtual TFloat  UBound(TRestr) throw(ERRange) = 0;
    virtual TFloat  LBound(TRestr) throw(ERRange) = 0;

    virtual TVarType    VarType(TVar) throw(ERRange) = 0;

    virtual char*   VarLabel(TVar,TOwnership = OWNED_BY_RECEIVER) throw(ERRange);
    virtual char*   RestrLabel(TRestr,TOwnership = OWNED_BY_RECEIVER) throw(ERRange);
    char*           UnifiedLabel(TRestr,TOwnership = OWNED_BY_RECEIVER) throw(ERRange);
    virtual TVar    VarIndex(char*) throw();
    virtual TRestr  RestrIndex(char*) throw();

    virtual TDirection  Direction() throw() = 0;

    virtual TFloat  Coeff(TRestr,TVar) throw(ERRange) = 0;

	virtual TVar    GetRow(TRestr i,TVar* index,double* val) throw(ERRange) = 0;
	// Gets Row i of the coefficient matrix and stores it in index
	// and val. val[j] is the coefficient of variable index[j] in row i. 
	// Returns the number of nonzeros of row i. index and val have to
	// be allocated before calling the method.

	virtual TRestr  GetColumn(TVar j,TRestr* index,double* val) throw(ERRange) = 0;
	// Gets Column j of the coefficient matrix and stores it in index
	// and val. val[i] is the coefficient of variable index[i] in row i. 
	// Returns the number of nonzeros of column j. index and val have to
	// be allocated before calling the method.

    virtual bool    VarVisibility(TVar) throw(ERRange) {return true;};
    virtual bool    RestrVisibility(TRestr) throw(ERRange) {return true;};

    
    // *************************************************************** //
    //                    Basis related information                    //
    // *************************************************************** //

    enum TRestrType     {BASIC_LB=0,BASIC_UB=1,NON_BASIC=2,RESTR_CANCELED=3};

    virtual TRestrType  RestrType(TRestr) throw(ERRange) = 0;
    virtual TRestr  Index(TVar) throw(ERRange) = 0;
    virtual TRestr  RowIndex(TRestr) throw(ERRange) = 0;
    virtual TVar    RevIndex(TRestr) throw(ERRange) = 0;

    enum TLowerUpper    {LOWER=0,UPPER=1};

    virtual void    SetRestrType(TRestr,TLowerUpper) throw(ERRange,ERRejected) = 0;
    virtual void    SetIndex(TRestr,TVar,TLowerUpper) throw(ERRange,ERRejected) = 0;

protected:

    TVar        pivotColumn;
    TRestr      pivotRow;
    TLowerUpper pivotDir;
    
public:

    TVar        PivotColumn() throw() {return pivotColumn;};
    TRestr      PivotRow() throw() {return pivotRow;};
    TLowerUpper PivotDirection() throw() {return pivotDir;};

    virtual void    ResetBasis() throw() = 0;
    virtual bool    Initial() throw() = 0;

    virtual TFloat  X(TVar) throw(ERRange) = 0;
    virtual TFloat  Y(TRestr,TLowerUpper) throw(ERRange) = 0;

    virtual TFloat  Tableau(TIndex,TIndex) throw(ERRange,ERRejected) = 0;
    virtual TFloat  BaseInverse(TIndex,TIndex) throw(ERRange,ERRejected) = 0;
    
    virtual void    Pivot(TIndex,TIndex,TLowerUpper) throw(ERRange,ERRejected) = 0;

    virtual TFloat  ObjVal() throw();
    virtual TFloat  Slack(TRestr,TLowerUpper) throw(ERRange);
    // Slack(i,LB)=A_ix-L_i bzw. x_i-l_i;
    // Slack(i,UB)=U_i-A_ix bzw. u_i-x_i;

    virtual bool    PrimalFeasible(TFloat epsilon = 0.01) throw();
    virtual bool    DualFeasible(TFloat epsilon = 0.01) throw();

    
    // *************************************************************** //
    //                           Algorithms                            //
    // *************************************************************** //

    enum TSimplexMethod {SIMPLEX_AUTO=0,SIMPLEX_PRIMAL=1,SIMPLEX_DUAL=2};
    enum TStartBasis    {START_AUTO=0,START_LRANGE=1,START_CURRENT=2};
    enum TPricing       {VAR_PRICING=0,FIRST_FIT=1};
    enum TQTest         {EXACT=0,MAX_ABS=1};

    virtual TFloat  SolvePrimal() throw() = 0;      // Phase II
    virtual TFloat  SolveDual() throw() = 0;        // Phase II
    virtual bool    StartPrimal() throw() = 0;      // Phase I
    virtual bool    StartDual() throw() = 0;        // Phase I

    virtual TVar    PricePrimal() throw(ERRejected) = 0;
    virtual TRestr  QTestPrimal(TVar) throw(ERRejected) = 0;
    virtual TRestr  PriceDual() throw(ERRejected) = 0;
    virtual TVar    QTestDual(TRestr) throw(ERRejected) = 0;
    
    virtual TFloat  SolveLP() throw(ERRejected);
    virtual TFloat  SolveMIP() throw(ERRejected);

    virtual void    AddCuttingPlane() throw(ERRejected);

    
    // *************************************************************** //
    //                          LP composition                         //
    // *************************************************************** //

    goblinILPWrapper*   DualForm() throw(ERRejected);
    goblinILPWrapper*   StandardForm() throw(ERRejected);
    goblinILPWrapper*   CanonicalForm() throw(ERRejected);
    void                FlipDirection() throw();

};



//****************************************************************************//
//                   Entry function and package information                   //
//****************************************************************************//


class goblinILPModule : public virtual goblinDataObject
{
public:

    goblinILPModule() throw() {};
    
    virtual ~goblinILPModule() throw() {};

    virtual goblinILPWrapper*
        NewInstance(TRestr,TVar,TIndex,goblinILPWrapper::TDirection,
            goblinController&) throw(ERRange) = 0;

    virtual goblinILPWrapper*
        ReadInstance(const char*,goblinController&) throw(ERRange) = 0;

    virtual goblinILPWrapper*
        Reinterprete(void*) throw(ERRange) = 0;

    virtual char*   Authors() throw() = 0;
    virtual int     MajorRelease() throw() = 0;
    virtual int     MinorRelease() throw() = 0;
    virtual char*   PatchLevel() throw() = 0;
    virtual char*   BuildDate() throw() = 0;
    virtual char*   License() throw() = 0;
    
    enum TLPOrientation {ROW_ORIENTED = 0,COLUMN_ORIENTED = 1};
    
    virtual TLPOrientation  Orientation() throw() = 0;
    
    virtual unsigned long   Size() throw() {return sizeof(goblinILPModule);};

};


#endif
