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