alpar@1381: /* -*- C++ -*- ladanyi@1435: * lemon/lp_cplex.cc - Part of LEMON, a generic C++ optimization library alpar@1381: * alpar@1381: * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport alpar@1381: * (Egervary Research Group on Combinatorial Optimization, EGRES). alpar@1381: * alpar@1381: * Permission to use, modify and distribute this software is granted alpar@1381: * provided that this copyright notice appears in all copies. For alpar@1381: * precise terms see the accompanying LICENSE file. alpar@1381: * alpar@1381: * This software is provided "AS IS" with no warranty of any kind, alpar@1381: * express or implied, and with no claim as to its suitability for any alpar@1381: * purpose. alpar@1381: * alpar@1381: */ athos@1405: #include athos@1405: #include alpar@1381: alpar@1381: ///\file alpar@1381: ///\brief Implementation of the LEMON-CPLEX lp solver interface. alpar@1381: namespace lemon { alpar@1381: alpar@1381: LpCplex::LpCplex() : LpSolverBase() { athos@1436: athos@1436: // env = CPXopenCPLEXdevelop(&status); athos@1436: env = CPXopenCPLEX(&status); alpar@1381: lp = CPXcreateprob(env, &status, "LP problem"); athos@1436: //CPXmsg (cpxresults, "Hello-bello\n"); alpar@1381: } alpar@1381: alpar@1381: LpCplex::~LpCplex() { athos@1436: CPXfreeprob(env,&lp); athos@1436: CPXcloseCPLEX(&env); alpar@1381: } alpar@1381: athos@1405: LpSolverBase &LpCplex::_newLp() athos@1405: { athos@1436: //The first approach opens a new environment athos@1436: LpCplex* newlp=new LpCplex(); athos@1436: return *newlp; athos@1405: } athos@1436: athos@1405: LpSolverBase &LpCplex::_copyLp() { athos@1436: //The first approach opens a new environment athos@1436: LpCplex* newlp=new LpCplex(); athos@1436: //The routine CPXcloneprob can be used to create a new CPLEX problem athos@1436: //object and copy all the problem data from an existing problem athos@1436: //object to it. Solution and starting information is not copied. athos@1436: newlp->lp = CPXcloneprob (env, lp, &status); athos@1436: return *newlp; athos@1405: } alpar@1381: alpar@1381: int LpCplex::_addCol() alpar@1381: { alpar@1381: int i = CPXgetnumcols (env, lp); alpar@1381: Value lb[1],ub[1]; alpar@1381: lb[0]=-INF;//-CPX_INFBOUND; alpar@1381: ub[0]=INF;//CPX_INFBOUND; alpar@1381: status = CPXnewcols (env, lp, 1, NULL, lb, ub, NULL, NULL); alpar@1381: return i; alpar@1381: } athos@1436: alpar@1381: alpar@1381: int LpCplex::_addRow() alpar@1381: { alpar@1381: //We want a row that is not constrained alpar@1381: char sense[1]; alpar@1381: sense[0]='L';//<= constraint alpar@1381: Value rhs[1]; alpar@1381: rhs[0]=INF; alpar@1381: int i = CPXgetnumrows (env, lp); alpar@1381: status = CPXnewrows (env, lp, 1, rhs, sense, NULL, NULL); alpar@1381: return i; alpar@1381: } athos@1432: athos@1432: athos@1432: void LpCplex::_eraseCol(int i) { athos@1436: CPXdelcols (env, lp, i, i); athos@1432: } athos@1432: athos@1432: void LpCplex::_eraseRow(int i) { athos@1436: CPXdelrows (env, lp, i, i); athos@1432: } athos@1432: alpar@1381: alpar@1381: ///\warning Data at index 0 is ignored in the arrays. alpar@1381: void LpCplex::_setRowCoeffs(int i, alpar@1381: int length, alpar@1381: int const * indices, alpar@1381: Value const * values ) alpar@1381: { alpar@1381: int rowlist[length+1]; alpar@1381: int* p=rowlist; alpar@1381: for (int k=1;k<=length;++k){ alpar@1381: rowlist[k]=i; alpar@1381: } alpar@1381: status = CPXchgcoeflist(env, lp, alpar@1381: length, alpar@1381: p+1, alpar@1381: const_cast(indices+1), alpar@1381: const_cast(values+1)); alpar@1381: } alpar@1381: alpar@1381: void LpCplex::_setColCoeffs(int i, alpar@1381: int length, alpar@1381: int const * indices, alpar@1381: Value const * values) alpar@1381: { alpar@1381: int collist[length+1]; alpar@1381: int* p=collist; alpar@1381: for (int k=1;k<=length;++k){ alpar@1381: collist[k]=i; alpar@1381: } alpar@1381: status = CPXchgcoeflist(env, lp, alpar@1381: length, alpar@1381: const_cast(indices+1), alpar@1381: p+1, alpar@1381: const_cast(values+1)); alpar@1381: } alpar@1381: athos@1431: void LpCplex::_setCoeff(int row, int col, Value value) athos@1431: { athos@1431: CPXchgcoef (env, lp, row, col, value); athos@1431: } athos@1431: alpar@1381: void LpCplex::_setColLowerBound(int i, Value value) alpar@1381: { alpar@1381: int indices[1]; alpar@1381: indices[0]=i; alpar@1381: char lu[1]; alpar@1381: lu[0]='L'; alpar@1381: Value bd[1]; alpar@1381: bd[0]=value; alpar@1381: status = CPXchgbds (env, lp, 1, indices, lu, bd); alpar@1381: alpar@1381: } alpar@1381: alpar@1381: void LpCplex::_setColUpperBound(int i, Value value) alpar@1381: { alpar@1381: int indices[1]; alpar@1381: indices[0]=i; alpar@1381: char lu[1]; alpar@1381: lu[0]='U'; alpar@1381: Value bd[1]; alpar@1381: bd[0]=value; alpar@1381: status = CPXchgbds (env, lp, 1, indices, lu, bd); alpar@1381: } alpar@1381: alpar@1381: //This will be easier to implement alpar@1381: void LpCplex::_setRowBounds(int i, Value lb, Value ub) alpar@1381: { alpar@1381: //Bad parameter alpar@1381: if (lb==INF || ub==-INF) { alpar@1381: //FIXME error alpar@1381: } athos@1405: alpar@1381: int cnt=1; alpar@1381: int indices[1]; alpar@1381: indices[0]=i; alpar@1381: char sense[1]; alpar@1381: alpar@1381: if (lb==-INF){ alpar@1381: sense[0]='L'; alpar@1381: CPXchgsense (env, lp, cnt, indices, sense); alpar@1381: CPXchgcoef (env, lp, i, -1, ub); athos@1405: alpar@1381: } alpar@1381: else{ alpar@1381: if (ub==INF){ alpar@1381: sense[0]='G'; alpar@1381: CPXchgsense (env, lp, cnt, indices, sense); alpar@1381: CPXchgcoef (env, lp, i, -1, lb); alpar@1381: } alpar@1381: else{ alpar@1381: if (lb == ub){ alpar@1381: sense[0]='E'; alpar@1381: CPXchgsense (env, lp, cnt, indices, sense); alpar@1381: CPXchgcoef (env, lp, i, -1, lb); alpar@1381: } alpar@1381: else{ alpar@1381: sense[0]='R'; alpar@1381: CPXchgsense (env, lp, cnt, indices, sense); alpar@1381: CPXchgcoef (env, lp, i, -1, lb); alpar@1381: CPXchgcoef (env, lp, i, -2, ub-lb); alpar@1381: } alpar@1381: } alpar@1381: } alpar@1381: } alpar@1381: athos@1405: // void LpCplex::_setRowLowerBound(int i, Value value) athos@1405: // { athos@1405: // //Not implemented, obsolete athos@1405: // } alpar@1381: athos@1405: // void LpCplex::_setRowUpperBound(int i, Value value) athos@1405: // { athos@1405: // //Not implemented, obsolete athos@1405: // // //TODO Ezt kell meg megirni athos@1405: // // //type of the problem athos@1405: // // char sense[1]; athos@1405: // // status = CPXgetsense (env, lp, sense, i, i); athos@1405: // // Value rhs[1]; athos@1405: // // status = CPXgetrhs (env, lp, rhs, i, i); alpar@1381: athos@1405: // // switch (sense[0]) { athos@1405: // // case 'L'://<= constraint athos@1405: // // break; athos@1405: // // case 'E'://= constraint athos@1405: // // break; athos@1405: // // case 'G'://>= constraint athos@1405: // // break; athos@1405: // // case 'R'://ranged constraint athos@1405: // // break; athos@1405: // // default: ; athos@1405: // // //FIXME error athos@1405: // // } alpar@1381: athos@1405: // // status = CPXchgcoef (env, lp, i, -2, value_rng); athos@1405: // } alpar@1381: alpar@1381: void LpCplex::_setObjCoeff(int i, Value obj_coef) alpar@1381: { alpar@1381: CPXchgcoef (env, lp, -1, i, obj_coef); alpar@1381: } alpar@1381: alpar@1381: void LpCplex::_clearObj() alpar@1381: { alpar@1381: for (int i=0;i< CPXgetnumcols (env, lp);++i){ alpar@1381: CPXchgcoef (env, lp, -1, i, 0); alpar@1381: } alpar@1381: alpar@1381: } alpar@1381: alpar@1381: LpCplex::SolveExitStatus LpCplex::_solve() alpar@1381: { alpar@1381: alpar@1381: status = CPXlpopt (env, lp); alpar@1381: if (status == 0){ alpar@1381: return SOLVED; alpar@1381: } alpar@1381: else{ alpar@1381: return UNSOLVED; alpar@1381: } alpar@1381: // int i= lpx_simplex(lp); alpar@1381: // switch (i) { alpar@1381: // case LPX_E_OK: alpar@1381: // return SOLVED; alpar@1381: // break; alpar@1381: // default: alpar@1381: // return UNSOLVED; alpar@1381: // } alpar@1381: } alpar@1381: alpar@1381: LpCplex::SolutionStatus LpCplex::_getPrimalStatus() alpar@1381: { athos@1407: //7.5-os cplex statusai athos@1407: // #define CPX_OPTIMAL 1 athos@1407: // #define CPX_INFEASIBLE 2 athos@1407: // #define CPX_UNBOUNDED 3 athos@1407: // #define CPX_OBJ_LIM 4 athos@1407: // #define CPX_IT_LIM_FEAS 5 athos@1407: // #define CPX_IT_LIM_INFEAS 6 athos@1407: // #define CPX_TIME_LIM_FEAS 7 athos@1407: // #define CPX_TIME_LIM_INFEAS 8 athos@1407: // #define CPX_NUM_BEST_FEAS 9 athos@1407: // #define CPX_NUM_BEST_INFEAS 10 athos@1407: // #define CPX_OPTIMAL_INFEAS 11 athos@1407: // #define CPX_ABORT_FEAS 12 athos@1407: // #define CPX_ABORT_INFEAS 13 athos@1407: // #define CPX_ABORT_DUAL_INFEAS 14 athos@1407: // #define CPX_ABORT_PRIM_INFEAS 15 athos@1407: // #define CPX_ABORT_PRIM_DUAL_INFEAS 16 athos@1407: // #define CPX_ABORT_PRIM_DUAL_FEAS 17 athos@1407: // #define CPX_ABORT_CROSSOVER 18 athos@1407: // #define CPX_INForUNBD 19 athos@1407: // #define CPX_PIVOT 20 athos@1407: athos@1407: // Ezeket hova tegyem: athos@1407: // ??case CPX_ABORT_DUAL_INFEAS athos@1407: // ??case CPX_ABORT_CROSSOVER athos@1407: // ??case CPX_INForUNBD athos@1407: // ??case CPX_PIVOT athos@1407: athos@1407: int stat = CPXgetstat (env, lp); athos@1407: switch (stat) { athos@1407: case 0: athos@1407: return UNDEFINED; //Undefined athos@1407: break; athos@1407: case CPX_OPTIMAL://Optimal athos@1407: return OPTIMAL; athos@1407: break; athos@1407: case CPX_UNBOUNDED://Unbounded athos@1407: return INFINITE; athos@1407: break; athos@1407: case CPX_INFEASIBLE://Infeasible athos@1407: case CPX_IT_LIM_INFEAS: athos@1407: case CPX_TIME_LIM_INFEAS: athos@1407: case CPX_NUM_BEST_INFEAS: athos@1407: case CPX_OPTIMAL_INFEAS: athos@1407: case CPX_ABORT_INFEAS: athos@1407: case CPX_ABORT_PRIM_INFEAS: athos@1407: case CPX_ABORT_PRIM_DUAL_INFEAS: athos@1407: return INFEASIBLE; athos@1407: break; athos@1407: case CPX_OBJ_LIM: athos@1407: case CPX_IT_LIM_FEAS: athos@1407: case CPX_TIME_LIM_FEAS: athos@1407: case CPX_NUM_BEST_FEAS: athos@1407: case CPX_ABORT_FEAS: athos@1407: case CPX_ABORT_PRIM_DUAL_FEAS: athos@1407: return FEASIBLE; athos@1407: break; athos@1407: default: athos@1407: return UNDEFINED; //Everything else comes here athos@1407: //FIXME error athos@1407: } athos@1407: athos@1407: athos@1407: //Nem tudom, hanyas cplex verzio statusai athos@1405: // CPX_STAT_ABORT_DUAL_OBJ_LIM athos@1405: // CPX_STAT_ABORT_IT_LIM athos@1405: // CPX_STAT_ABORT_OBJ_LIM athos@1405: // CPX_STAT_ABORT_PRIM_OBJ_LIM athos@1405: // CPX_STAT_ABORT_TIME_LIM athos@1405: // CPX_STAT_ABORT_USER athos@1405: // CPX_STAT_FEASIBLE_RELAXED athos@1405: // CPX_STAT_INFEASIBLE athos@1405: // CPX_STAT_INForUNBD athos@1405: // CPX_STAT_NUM_BEST athos@1405: // CPX_STAT_OPTIMAL athos@1405: // CPX_STAT_OPTIMAL_FACE_UNBOUNDED athos@1405: // CPX_STAT_OPTIMAL_INFEAS athos@1405: // CPX_STAT_OPTIMAL_RELAXED athos@1405: // CPX_STAT_UNBOUNDED athos@1405: athos@1407: // int stat = CPXgetstat (env, lp); athos@1407: // switch (stat) { athos@1407: // case CPX_STAT_OPTIMAL://Optimal athos@1407: // return OPTIMAL; athos@1407: // break; athos@1407: // case CPX_STAT_INFEASIBLE://Infeasible athos@1407: // return INFEASIBLE; athos@1407: // break; athos@1407: // case CPX_STAT_UNBOUNDED://Unbounded athos@1407: // return INFINITE; athos@1407: // break; athos@1407: // case CPX_STAT_NUM_BEST://Feasible athos@1407: // return FEASIBLE; athos@1407: // break; athos@1407: // default: athos@1407: // return UNDEFINED; //Everything else comes here athos@1407: // //FIXME error athos@1407: // } athos@1407: alpar@1381: } alpar@1381: alpar@1381: LpCplex::Value LpCplex::_getPrimal(int i) alpar@1381: { alpar@1381: Value x; alpar@1381: CPXgetx (env, lp, &x, i, i); alpar@1381: return x; alpar@1381: } alpar@1381: alpar@1381: LpCplex::Value LpCplex::_getPrimalValue() alpar@1381: { athos@1405: Value objval; athos@1405: //method = CPXgetmethod (env, lp); athos@1405: status = CPXgetobjval (env, lp, &objval); athos@1405: return objval; alpar@1381: } alpar@1381: alpar@1381: alpar@1381: alpar@1381: alpar@1381: void LpCplex::_setMax() alpar@1381: { alpar@1381: CPXchgobjsen (env, lp, CPX_MAX); alpar@1381: } alpar@1381: void LpCplex::_setMin() alpar@1381: { alpar@1381: CPXchgobjsen (env, lp, CPX_MIN); alpar@1381: } alpar@1381: alpar@1381: } //namespace lemon alpar@1381: