alpar@1381: /* -*- C++ -*- alpar@1381: * alpar@1956: * This file is a part of LEMON, a generic C++ optimization library alpar@1956: * alpar@2553: * Copyright (C) 2003-2008 alpar@1956: * 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: */ alpar@1956: 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: // env = CPXopenCPLEXdevelop(&status); athos@1436: env = CPXopenCPLEX(&status); alpar@1381: lp = CPXcreateprob(env, &status, "LP problem"); 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@2328: ///\bug FixID data is not copied! 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@1508: newlp->lp = CPXcloneprob(env, lp, &status); athos@1436: return *newlp; athos@1405: } alpar@1381: alpar@1381: int LpCplex::_addCol() alpar@1381: { athos@1508: 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; athos@1508: 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; athos@1508: int i = CPXgetnumrows(env, lp); athos@1508: 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@1508: CPXdelcols(env, lp, i, i); athos@1432: } athos@1432: athos@1432: void LpCplex::_eraseRow(int i) { athos@1508: CPXdelrows(env, lp, i, i); athos@1432: } alpar@1895: deba@2366: void LpCplex::_getColName(int col, std::string &name) const alpar@1895: { klao@1950: ///\bug Untested klao@1950: int storespace; klao@1950: CPXgetcolname(env, lp, 0, 0, 0, &storespace, col, col); klao@1950: klao@1950: storespace *= -1; klao@1950: char buf[storespace]; klao@1950: char *names[1]; klao@1950: int dontcare; klao@1950: ///\bug return code unchecked for error klao@1950: CPXgetcolname(env, lp, names, buf, storespace, &dontcare, col, col); klao@1950: name = names[0]; alpar@1895: } alpar@1895: alpar@1895: void LpCplex::_setColName(int col, const std::string &name) alpar@1895: { alpar@1895: ///\bug Untested klao@1950: char *names[1]; klao@1950: names[0] = const_cast(name.c_str()); klao@1950: ///\bug return code unchecked for error klao@1950: CPXchgcolname(env, lp, 1, &col, names); alpar@1895: } deba@2366: deba@2366: int LpCplex::_colByName(const std::string& name) const deba@2366: { deba@2366: int index; deba@2366: if (CPXgetcolindex(env, lp, deba@2366: const_cast(name.c_str()), &index) == 0) { deba@2366: return index; deba@2366: } deba@2366: return -1; deba@2366: } alpar@1381: alpar@1381: ///\warning Data at index 0 is ignored in the arrays. deba@2364: void LpCplex::_setRowCoeffs(int i, ConstRowIterator b, ConstRowIterator e) alpar@1381: { deba@2312: std::vector indices; deba@2312: std::vector rowlist; deba@2312: std::vector values; deba@2312: deba@2364: for(ConstRowIterator it=b; it!=e; ++it) { deba@2312: indices.push_back(it->first); deba@2312: values.push_back(it->second); deba@2312: rowlist.push_back(i); alpar@1381: } deba@2312: deba@2312: status = CPXchgcoeflist(env, lp, values.size(), deba@2312: &rowlist[0], &indices[0], &values[0]); alpar@1381: } deba@2364: athos@2415: void LpCplex::_getRowCoeffs(int i, RowIterator b) const { deba@2364: /// \todo implement deba@2364: } alpar@1381: deba@2364: void LpCplex::_setColCoeffs(int i, ConstColIterator b, ConstColIterator e) alpar@1381: { deba@2312: std::vector indices; deba@2312: std::vector collist; deba@2312: std::vector values; deba@2312: deba@2364: for(ConstColIterator it=b; it!=e; ++it) { deba@2312: indices.push_back(it->first); deba@2312: values.push_back(it->second); deba@2312: collist.push_back(i); alpar@1381: } deba@2312: deba@2312: status = CPXchgcoeflist(env, lp, values.size(), deba@2312: &indices[0], &collist[0], &values[0]); alpar@1381: } deba@2364: athos@2415: void LpCplex::_getColCoeffs(int i, ColIterator b) const { deba@2364: /// \todo implement deba@2364: } alpar@1381: athos@1431: void LpCplex::_setCoeff(int row, int col, Value value) athos@1431: { athos@1508: CPXchgcoef(env, lp, row, col, value); athos@1431: } athos@1431: deba@2366: LpCplex::Value LpCplex::_getCoeff(int row, int col) const athos@2361: { athos@2361: LpCplex::Value value; athos@2361: CPXgetcoef(env, lp, row, col, &value); athos@2361: return value; athos@2361: } athos@2361: 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; athos@1508: status = CPXchgbds(env, lp, 1, indices, lu, bd); alpar@1381: alpar@1381: } athos@2361: deba@2366: LpCplex::Value LpCplex::_getColLowerBound(int i) const athos@2361: { athos@2361: LpCplex::Value x; athos@2361: CPXgetlb (env, lp, &x, i, i); athos@2361: return x; athos@2361: } 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; athos@1508: status = CPXchgbds(env, lp, 1, indices, lu, bd); alpar@1381: } alpar@1381: deba@2366: LpCplex::Value LpCplex::_getColUpperBound(int i) const athos@2361: { athos@2361: LpCplex::Value x; athos@2361: CPXgetub (env, lp, &x, i, i); athos@2361: return x; athos@2361: } athos@2361: 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'; athos@1508: CPXchgsense(env, lp, cnt, indices, sense); athos@1508: CPXchgcoef(env, lp, i, -1, ub); athos@1405: alpar@1381: } alpar@1381: else{ alpar@1381: if (ub==INF){ alpar@1381: sense[0]='G'; athos@1508: CPXchgsense(env, lp, cnt, indices, sense); athos@1508: CPXchgcoef(env, lp, i, -1, lb); alpar@1381: } alpar@1381: else{ alpar@1381: if (lb == ub){ alpar@1381: sense[0]='E'; athos@1508: CPXchgsense(env, lp, cnt, indices, sense); athos@1508: CPXchgcoef(env, lp, i, -1, lb); alpar@1381: } alpar@1381: else{ alpar@1381: sense[0]='R'; athos@1508: CPXchgsense(env, lp, cnt, indices, sense); athos@1508: CPXchgcoef(env, lp, i, -1, lb); athos@1508: 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@1508: // // status = CPXgetsense(env, lp, sense, i, i); athos@1405: // // Value rhs[1]; athos@1508: // // 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@1508: // // status = CPXchgcoef(env, lp, i, -2, value_rng); athos@1405: // } alpar@1381: deba@2366: void LpCplex::_getRowBounds(int i, Value &lb, Value &ub) const athos@2361: { athos@2361: char sense; athos@2361: CPXgetsense(env, lp, &sense,i,i); athos@2361: lb=-INF; athos@2361: ub=INF; athos@2361: switch (sense) athos@2361: { athos@2361: case 'L': athos@2361: CPXgetcoef(env, lp, i, -1, &ub); athos@2361: break; athos@2361: case 'G': athos@2361: CPXgetcoef(env, lp, i, -1, &lb); athos@2361: break; athos@2361: case 'E': athos@2361: CPXgetcoef(env, lp, i, -1, &lb); athos@2361: ub=lb; athos@2361: break; athos@2361: case 'R': athos@2361: CPXgetcoef(env, lp, i, -1, &lb); athos@2361: Value x; athos@2361: CPXgetcoef(env, lp, i, -2, &x); athos@2361: ub=lb+x; athos@2361: break; athos@2361: } athos@2361: } athos@2361: alpar@1381: void LpCplex::_setObjCoeff(int i, Value obj_coef) alpar@1381: { athos@1508: CPXchgcoef(env, lp, -1, i, obj_coef); alpar@1381: } alpar@1381: deba@2366: LpCplex::Value LpCplex::_getObjCoeff(int i) const athos@2361: { athos@2361: Value x; athos@2361: CPXgetcoef(env, lp, -1, i, &x); athos@2361: return x; athos@2361: } athos@2361: alpar@1381: void LpCplex::_clearObj() alpar@1381: { athos@1508: for (int i=0;i< CPXgetnumcols(env, lp);++i){ athos@1508: CPXchgcoef(env, lp, -1, i, 0); alpar@1381: } alpar@1381: alpar@1381: } athos@1458: // The routine returns zero unless an error occurred during the athos@1458: // optimization. Examples of errors include exhausting available athos@1458: // memory (CPXERR_NO_MEMORY) or encountering invalid data in the athos@1458: // CPLEX problem object (CPXERR_NO_PROBLEM). Exceeding a athos@1458: // user-specified CPLEX limit, or proving the model infeasible or athos@1458: // unbounded, are not considered errors. Note that a zero return athos@1458: // value does not necessarily mean that a solution exists. Use query athos@1458: // routines CPXsolninfo, CPXgetstat, and CPXsolution to obtain athos@1458: // further information about the status of the optimization. alpar@1381: LpCplex::SolveExitStatus LpCplex::_solve() alpar@1381: { athos@1458: //CPX_PARAM_LPMETHOD athos@1508: status = CPXlpopt(env, lp); athos@1542: //status = CPXprimopt(env, lp); athos@2218: #if CPX_VERSION >= 800 ladanyi@2168: if (status) ladanyi@2168: { ladanyi@2168: return UNSOLVED; ladanyi@2168: } ladanyi@2168: else ladanyi@2168: { ladanyi@2168: switch (CPXgetstat(env, lp)) ladanyi@2168: { ladanyi@2168: case CPX_STAT_OPTIMAL: ladanyi@2168: case CPX_STAT_INFEASIBLE: ladanyi@2168: case CPX_STAT_UNBOUNDED: ladanyi@2168: return SOLVED; ladanyi@2168: default: ladanyi@2168: return UNSOLVED; ladanyi@2168: } ladanyi@2168: } ladanyi@2168: #else alpar@1381: if (status == 0){ athos@1458: //We want to exclude some cases athos@1508: switch (CPXgetstat(env, lp)){ athos@1458: case CPX_OBJ_LIM: athos@1458: case CPX_IT_LIM_FEAS: athos@1458: case CPX_IT_LIM_INFEAS: athos@1458: case CPX_TIME_LIM_FEAS: athos@1458: case CPX_TIME_LIM_INFEAS: athos@1458: return UNSOLVED; athos@1458: default: athos@1458: return SOLVED; athos@1458: } alpar@1381: } alpar@1381: else{ alpar@1381: return UNSOLVED; alpar@1381: } ladanyi@2168: #endif alpar@1381: } alpar@1381: deba@2366: LpCplex::Value LpCplex::_getPrimal(int i) const athos@1460: { athos@1460: Value x; athos@1508: CPXgetx(env, lp, &x, i, i); athos@1460: return x; athos@1460: } marci@1787: deba@2366: LpCplex::Value LpCplex::_getDual(int i) const marci@1787: { marci@1787: Value y; klao@1798: CPXgetpi(env, lp, &y, i, i); marci@1787: return y; marci@1787: } athos@1460: deba@2366: LpCplex::Value LpCplex::_getPrimalValue() const athos@1460: { athos@1460: Value objval; athos@1460: //method = CPXgetmethod (env, lp); athos@1508: //printf("CPXgetprobtype %d \n",CPXgetprobtype(env,lp)); athos@2415: CPXgetobjval(env, lp, &objval); athos@1508: //printf("Objective value: %g \n",objval); athos@1460: return objval; athos@1460: } deba@2366: bool LpCplex::_isBasicCol(int i) const deba@2366: { marci@1841: int cstat[CPXgetnumcols(env, lp)]; marci@1841: CPXgetbase(env, lp, cstat, NULL); marci@1841: return (cstat[i]==CPX_BASIC); marci@1840: } athos@1407: athos@1458: //7.5-os cplex statusai (Vigyazat: a 9.0-asei masok!) athos@1458: // This table lists the statuses, returned by the CPXgetstat() routine, for solutions to LP problems or mixed integer problems. If no solution exists, the return value is zero. athos@1458: athos@1458: // For Simplex, Barrier athos@1458: // 1 CPX_OPTIMAL athos@1458: // Optimal solution found athos@1458: // 2 CPX_INFEASIBLE athos@1458: // Problem infeasible athos@1458: // 3 CPX_UNBOUNDED athos@1458: // Problem unbounded athos@1458: // 4 CPX_OBJ_LIM athos@1458: // Objective limit exceeded in Phase II athos@1458: // 5 CPX_IT_LIM_FEAS athos@1458: // Iteration limit exceeded in Phase II athos@1458: // 6 CPX_IT_LIM_INFEAS athos@1458: // Iteration limit exceeded in Phase I athos@1458: // 7 CPX_TIME_LIM_FEAS athos@1458: // Time limit exceeded in Phase II athos@1458: // 8 CPX_TIME_LIM_INFEAS athos@1458: // Time limit exceeded in Phase I athos@1458: // 9 CPX_NUM_BEST_FEAS athos@1458: // Problem non-optimal, singularities in Phase II athos@1458: // 10 CPX_NUM_BEST_INFEAS athos@1458: // Problem non-optimal, singularities in Phase I athos@1458: // 11 CPX_OPTIMAL_INFEAS athos@1458: // Optimal solution found, unscaled infeasibilities athos@1458: // 12 CPX_ABORT_FEAS athos@1458: // Aborted in Phase II athos@1458: // 13 CPX_ABORT_INFEAS athos@1458: // Aborted in Phase I athos@1458: // 14 CPX_ABORT_DUAL_INFEAS athos@1458: // Aborted in barrier, dual infeasible athos@1458: // 15 CPX_ABORT_PRIM_INFEAS athos@1458: // Aborted in barrier, primal infeasible athos@1458: // 16 CPX_ABORT_PRIM_DUAL_INFEAS athos@1458: // Aborted in barrier, primal and dual infeasible athos@1458: // 17 CPX_ABORT_PRIM_DUAL_FEAS athos@1458: // Aborted in barrier, primal and dual feasible athos@1458: // 18 CPX_ABORT_CROSSOVER athos@1458: // Aborted in crossover athos@1458: // 19 CPX_INForUNBD athos@1458: // Infeasible or unbounded athos@1458: // 20 CPX_PIVOT athos@1458: // User pivot used athos@1458: // athos@1407: // Ezeket hova tegyem: athos@1407: // ??case CPX_ABORT_DUAL_INFEAS athos@1407: // ??case CPX_ABORT_CROSSOVER athos@1407: // ??case CPX_INForUNBD athos@1542: // ??case CPX_PIVOT athos@1542: athos@1542: //Some more interesting stuff: athos@1542: athos@1542: // CPX_PARAM_LPMETHOD 1062 int LPMETHOD athos@1542: // 0 Automatic athos@1542: // 1 Primal Simplex athos@1542: // 2 Dual Simplex athos@1542: // 3 Network Simplex athos@1542: // 4 Standard Barrier athos@1542: // Default: 0 athos@1542: // Description: Method for linear optimization. athos@1542: // Determines which algorithm is used when CPXlpopt() (or "optimize" in the Interactive Optimizer) is called. Currently the behavior of the "Automatic" setting is that CPLEX simply invokes the dual simplex method, but this capability may be expanded in the future so that CPLEX chooses the method based on problem characteristics athos@1542: void statusSwitch(CPXENVptr env,int& stat){ ladanyi@2168: #if CPX_VERSION < 900 athos@1542: int lpmethod; athos@1542: CPXgetintparam (env,CPX_PARAM_LPMETHOD,&lpmethod); athos@1542: if (lpmethod==2){ athos@1542: if (stat==CPX_UNBOUNDED){ athos@1542: stat=CPX_INFEASIBLE; athos@1542: } athos@1542: else{ athos@1542: if (stat==CPX_INFEASIBLE) athos@1542: stat=CPX_UNBOUNDED; athos@1542: } athos@1542: } ladanyi@2168: #endif athos@1542: } athos@1407: deba@2366: LpCplex::SolutionStatus LpCplex::_getPrimalStatus() const athos@1458: { athos@2218: //Unboundedness not treated well: the following is from cplex 9.0 doc athos@2218: // About Unboundedness athos@2218: athos@2218: // The treatment of models that are unbounded involves a few athos@2218: // subtleties. Specifically, a declaration of unboundedness means that athos@2218: // ILOG CPLEX has determined that the model has an unbounded athos@2218: // ray. Given any feasible solution x with objective z, a multiple of athos@2218: // the unbounded ray can be added to x to give a feasible solution athos@2218: // with objective z-1 (or z+1 for maximization models). Thus, if a athos@2218: // feasible solution exists, then the optimal objective is athos@2218: // unbounded. Note that ILOG CPLEX has not necessarily concluded that athos@2218: // a feasible solution exists. Users can call the routine CPXsolninfo athos@2218: // to determine whether ILOG CPLEX has also concluded that the model athos@2218: // has a feasible solution. athos@2218: athos@1508: int stat = CPXgetstat(env, lp); athos@2218: #if CPX_VERSION >= 800 ladanyi@2168: switch (stat) ladanyi@2168: { ladanyi@2168: case CPX_STAT_OPTIMAL: ladanyi@2168: return OPTIMAL; ladanyi@2168: case CPX_STAT_UNBOUNDED: ladanyi@2168: return INFINITE; ladanyi@2168: case CPX_STAT_INFEASIBLE: ladanyi@2168: return INFEASIBLE; ladanyi@2168: default: ladanyi@2168: return UNDEFINED; ladanyi@2168: } ladanyi@2168: #else athos@1542: statusSwitch(env,stat); athos@1542: //CPXgetstat(env, lp); athos@1508: //printf("A primal status: %d, CPX_OPTIMAL=%d \n",stat,CPX_OPTIMAL); athos@1407: switch (stat) { athos@1407: case 0: athos@1407: return UNDEFINED; //Undefined athos@1407: case CPX_OPTIMAL://Optimal athos@1407: return OPTIMAL; athos@1407: case CPX_UNBOUNDED://Unbounded athos@1542: return INFEASIBLE;//In case of dual simplex athos@1542: //return INFINITE; athos@1407: case CPX_INFEASIBLE://Infeasible athos@1458: // case CPX_IT_LIM_INFEAS: athos@1458: // case CPX_TIME_LIM_INFEAS: athos@1458: // case CPX_NUM_BEST_INFEAS: athos@1458: // case CPX_OPTIMAL_INFEAS: athos@1458: // case CPX_ABORT_INFEAS: athos@1458: // case CPX_ABORT_PRIM_INFEAS: athos@1458: // case CPX_ABORT_PRIM_DUAL_INFEAS: athos@1542: return INFINITE;//In case of dual simplex athos@1542: //return INFEASIBLE; athos@1458: // case CPX_OBJ_LIM: athos@1458: // case CPX_IT_LIM_FEAS: athos@1458: // case CPX_TIME_LIM_FEAS: athos@1458: // case CPX_NUM_BEST_FEAS: athos@1458: // case CPX_ABORT_FEAS: athos@1458: // case CPX_ABORT_PRIM_DUAL_FEAS: athos@1458: // return FEASIBLE; athos@1407: default: athos@1407: return UNDEFINED; //Everything else comes here athos@1407: //FIXME error athos@1407: } ladanyi@2168: #endif athos@1458: } athos@1407: athos@1458: //9.0-as 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: deba@2366: LpCplex::SolutionStatus LpCplex::_getDualStatus() const athos@1458: { athos@1508: int stat = CPXgetstat(env, lp); athos@2218: #if CPX_VERSION >= 800 ladanyi@2168: switch (stat) ladanyi@2168: { ladanyi@2168: case CPX_STAT_OPTIMAL: ladanyi@2168: return OPTIMAL; ladanyi@2168: case CPX_STAT_UNBOUNDED: ladanyi@2168: return INFEASIBLE; ladanyi@2168: default: ladanyi@2168: return UNDEFINED; ladanyi@2168: } ladanyi@2168: #else athos@1542: statusSwitch(env,stat); athos@1458: switch (stat) { athos@1458: case 0: athos@1458: return UNDEFINED; //Undefined athos@1458: case CPX_OPTIMAL://Optimal athos@1458: return OPTIMAL; athos@1458: case CPX_UNBOUNDED: athos@1458: return INFEASIBLE; athos@1458: default: athos@1458: return UNDEFINED; //Everything else comes here athos@1458: //FIXME error athos@1458: } ladanyi@2168: #endif athos@1473: } alpar@1381: deba@2366: LpCplex::ProblemTypes LpCplex::_getProblemType() const alpar@1381: { athos@1508: int stat = CPXgetstat(env, lp); athos@2218: #if CPX_VERSION >= 800 ladanyi@2168: switch (stat) ladanyi@2168: { ladanyi@2168: case CPX_STAT_OPTIMAL: ladanyi@2168: return PRIMAL_DUAL_FEASIBLE; ladanyi@2168: case CPX_STAT_UNBOUNDED: ladanyi@2168: return PRIMAL_FEASIBLE_DUAL_INFEASIBLE; ladanyi@2168: default: ladanyi@2168: return UNKNOWN; ladanyi@2168: } ladanyi@2168: #else athos@1460: switch (stat) { athos@1460: case CPX_OPTIMAL://Optimal athos@1460: return PRIMAL_DUAL_FEASIBLE; athos@1460: case CPX_UNBOUNDED: athos@1460: return PRIMAL_FEASIBLE_DUAL_INFEASIBLE; athos@1460: // return PRIMAL_INFEASIBLE_DUAL_FEASIBLE; athos@1460: // return PRIMAL_DUAL_INFEASIBLE; athos@1460: athos@1460: //Seems to be that this is all we can say for sure athos@1460: default: athos@1460: //In all other cases athos@1460: return UNKNOWN; athos@1460: //FIXME error athos@1460: } ladanyi@2168: #endif athos@1473: } alpar@1381: alpar@1381: void LpCplex::_setMax() alpar@1381: { athos@1508: CPXchgobjsen(env, lp, CPX_MAX); alpar@1381: } alpar@1381: void LpCplex::_setMin() alpar@1381: { athos@1508: CPXchgobjsen(env, lp, CPX_MIN); alpar@1381: } athos@2361: deba@2366: bool LpCplex::_isMax() const athos@2361: { athos@2361: if (CPXgetobjsen(env, lp)==CPX_MAX) athos@2361: return true; athos@2361: else athos@2361: return false; athos@2361: } alpar@1381: alpar@1381: } //namespace lemon alpar@1381: