3 * This file is a part of LEMON, a generic C++ optimization library
5 * Copyright (C) 2003-2008
6 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 * (Egervary Research Group on Combinatorial Optimization, EGRES).
9 * Permission to use, modify and distribute this software is granted
10 * provided that this copyright notice appears in all copies. For
11 * precise terms see the accompanying LICENSE file.
13 * This software is provided "AS IS" with no warranty of any kind,
14 * express or implied, and with no claim as to its suitability for any
21 #include<lemon/lp_cplex.h>
24 ///\brief Implementation of the LEMON-CPLEX lp solver interface.
28 // env = CPXopenCPLEXdevelop(&status);
29 env = CPXopenCPLEX(&status);
30 lp = CPXcreateprob(env, &status, "LP problem");
33 LpCplex::LpCplex(const LpCplex& cplex) : LpSolverBase() {
34 env = CPXopenCPLEX(&status);
35 lp = CPXcloneprob(env, cplex.lp, &status);
45 LpSolverBase* LpCplex::_newLp()
47 //The first approach opens a new environment
51 LpSolverBase* LpCplex::_copyLp() {
52 return new LpCplex(*this);
55 int LpCplex::_addCol()
57 int i = CPXgetnumcols(env, lp);
61 status = CPXnewcols(env, lp, 1, NULL, lb, ub, NULL, NULL);
66 int LpCplex::_addRow()
68 //We want a row that is not constrained
70 sense[0]='L';//<= constraint
73 int i = CPXgetnumrows(env, lp);
74 status = CPXnewrows(env, lp, 1, rhs, sense, NULL, NULL);
79 void LpCplex::_eraseCol(int i) {
80 CPXdelcols(env, lp, i, i);
83 void LpCplex::_eraseRow(int i) {
84 CPXdelrows(env, lp, i, i);
87 void LpCplex::_getColName(int col, std::string &name) const
91 CPXgetcolname(env, lp, 0, 0, 0, &storespace, col, col);
92 if (storespace == 0) {
98 std::vector<char> buf(storespace);
101 ///\bug return code unchecked for error
102 CPXgetcolname(env, lp, names, &*buf.begin(), storespace, &dontcare, col, col);
106 void LpCplex::_setColName(int col, const std::string &name)
110 names[0] = const_cast<char*>(name.c_str());
111 ///\bug return code unchecked for error
112 CPXchgcolname(env, lp, 1, &col, names);
115 int LpCplex::_colByName(const std::string& name) const
118 if (CPXgetcolindex(env, lp,
119 const_cast<char*>(name.c_str()), &index) == 0) {
125 ///\warning Data at index 0 is ignored in the arrays.
126 void LpCplex::_setRowCoeffs(int i, ConstRowIterator b, ConstRowIterator e)
128 std::vector<int> indices;
129 std::vector<int> rowlist;
130 std::vector<Value> values;
132 for(ConstRowIterator it=b; it!=e; ++it) {
133 indices.push_back(it->first);
134 values.push_back(it->second);
135 rowlist.push_back(i);
138 status = CPXchgcoeflist(env, lp, values.size(),
139 &rowlist[0], &indices[0], &values[0]);
142 void LpCplex::_getRowCoeffs(int i, RowIterator b) const {
143 int tmp1, tmp2, tmp3, length;
144 CPXgetrows(env, lp, &tmp1, &tmp2, 0, 0, 0, &length, i, i);
147 std::vector<int> indices(length);
148 std::vector<double> values(length);
150 CPXgetrows(env, lp, &tmp1, &tmp2, &indices[0], &values[0],
151 length, &tmp3, i, i);
153 for (int i = 0; i < length; ++i) {
154 *b = std::make_pair(indices[i], values[i]);
161 void LpCplex::_setColCoeffs(int i, ConstColIterator b, ConstColIterator e)
163 std::vector<int> indices;
164 std::vector<int> collist;
165 std::vector<Value> values;
167 for(ConstColIterator it=b; it!=e; ++it) {
168 indices.push_back(it->first);
169 values.push_back(it->second);
170 collist.push_back(i);
173 status = CPXchgcoeflist(env, lp, values.size(),
174 &indices[0], &collist[0], &values[0]);
177 void LpCplex::_getColCoeffs(int i, ColIterator b) const {
179 int tmp1, tmp2, tmp3, length;
180 CPXgetcols(env, lp, &tmp1, &tmp2, 0, 0, 0, &length, i, i);
183 std::vector<int> indices(length);
184 std::vector<double> values(length);
186 CPXgetcols(env, lp, &tmp1, &tmp2, &indices[0], &values[0],
187 length, &tmp3, i, i);
189 for (int i = 0; i < length; ++i) {
190 *b = std::make_pair(indices[i], values[i]);
196 void LpCplex::_setCoeff(int row, int col, Value value)
198 CPXchgcoef(env, lp, row, col, value);
201 LpCplex::Value LpCplex::_getCoeff(int row, int col) const
203 LpCplex::Value value;
204 CPXgetcoef(env, lp, row, col, &value);
208 void LpCplex::_setColLowerBound(int i, Value value)
216 status = CPXchgbds(env, lp, 1, indices, lu, bd);
220 LpCplex::Value LpCplex::_getColLowerBound(int i) const
223 CPXgetlb (env, lp, &x, i, i);
224 if (x <= -CPX_INFBOUND) x = -INF;
228 void LpCplex::_setColUpperBound(int i, Value value)
236 status = CPXchgbds(env, lp, 1, indices, lu, bd);
239 LpCplex::Value LpCplex::_getColUpperBound(int i) const
242 CPXgetub (env, lp, &x, i, i);
243 if (x >= CPX_INFBOUND) x = INF;
247 //This will be easier to implement
248 void LpCplex::_setRowBounds(int i, Value lb, Value ub)
251 if (lb==INF || ub==-INF) {
262 CPXchgsense(env, lp, cnt, indices, sense);
263 CPXchgcoef(env, lp, i, -1, ub);
269 CPXchgsense(env, lp, cnt, indices, sense);
270 CPXchgcoef(env, lp, i, -1, lb);
275 CPXchgsense(env, lp, cnt, indices, sense);
276 CPXchgcoef(env, lp, i, -1, lb);
280 CPXchgsense(env, lp, cnt, indices, sense);
281 CPXchgcoef(env, lp, i, -1, lb);
282 CPXchgcoef(env, lp, i, -2, ub-lb);
288 // void LpCplex::_setRowLowerBound(int i, Value value)
290 // //Not implemented, obsolete
293 // void LpCplex::_setRowUpperBound(int i, Value value)
295 // //Not implemented, obsolete
296 // // //TODO Ezt kell meg megirni
297 // // //type of the problem
299 // // status = CPXgetsense(env, lp, sense, i, i);
301 // // status = CPXgetrhs(env, lp, rhs, i, i);
303 // // switch (sense[0]) {
304 // // case 'L'://<= constraint
306 // // case 'E'://= constraint
308 // // case 'G'://>= constraint
310 // // case 'R'://ranged constraint
316 // // status = CPXchgcoef(env, lp, i, -2, value_rng);
319 void LpCplex::_getRowBounds(int i, Value &lb, Value &ub) const
322 CPXgetsense(env, lp, &sense,i,i);
328 CPXgetcoef(env, lp, i, -1, &ub);
331 CPXgetcoef(env, lp, i, -1, &lb);
334 CPXgetcoef(env, lp, i, -1, &lb);
338 CPXgetcoef(env, lp, i, -1, &lb);
340 CPXgetcoef(env, lp, i, -2, &x);
346 void LpCplex::_setObjCoeff(int i, Value obj_coef)
348 CPXchgcoef(env, lp, -1, i, obj_coef);
351 LpCplex::Value LpCplex::_getObjCoeff(int i) const
354 CPXgetcoef(env, lp, -1, i, &x);
358 void LpCplex::_clearObj()
360 for (int i=0;i< CPXgetnumcols(env, lp);++i){
361 CPXchgcoef(env, lp, -1, i, 0);
365 // The routine returns zero unless an error occurred during the
366 // optimization. Examples of errors include exhausting available
367 // memory (CPXERR_NO_MEMORY) or encountering invalid data in the
368 // CPLEX problem object (CPXERR_NO_PROBLEM). Exceeding a
369 // user-specified CPLEX limit, or proving the model infeasible or
370 // unbounded, are not considered errors. Note that a zero return
371 // value does not necessarily mean that a solution exists. Use query
372 // routines CPXsolninfo, CPXgetstat, and CPXsolution to obtain
373 // further information about the status of the optimization.
374 LpCplex::SolveExitStatus LpCplex::_solve()
377 status = CPXlpopt(env, lp);
378 //status = CPXprimopt(env, lp);
379 #if CPX_VERSION >= 800
386 switch (CPXgetstat(env, lp))
388 case CPX_STAT_OPTIMAL:
389 case CPX_STAT_INFEASIBLE:
390 case CPX_STAT_UNBOUNDED:
398 //We want to exclude some cases
399 switch (CPXgetstat(env, lp)){
401 case CPX_IT_LIM_FEAS:
402 case CPX_IT_LIM_INFEAS:
403 case CPX_TIME_LIM_FEAS:
404 case CPX_TIME_LIM_INFEAS:
416 LpCplex::Value LpCplex::_getPrimal(int i) const
419 CPXgetx(env, lp, &x, i, i);
423 LpCplex::Value LpCplex::_getDual(int i) const
426 CPXgetpi(env, lp, &y, i, i);
430 LpCplex::Value LpCplex::_getPrimalValue() const
433 //method = CPXgetmethod (env, lp);
434 //printf("CPXgetprobtype %d \n",CPXgetprobtype(env,lp));
435 CPXgetobjval(env, lp, &objval);
436 //printf("Objective value: %g \n",objval);
439 bool LpCplex::_isBasicCol(int i) const
441 std::vector<int> cstat(CPXgetnumcols(env, lp));
442 CPXgetbase(env, lp, &*cstat.begin(), NULL);
443 return (cstat[i]==CPX_BASIC);
446 //7.5-os cplex statusai (Vigyazat: a 9.0-asei masok!)
447 // 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.
449 // For Simplex, Barrier
451 // Optimal solution found
453 // Problem infeasible
457 // Objective limit exceeded in Phase II
459 // Iteration limit exceeded in Phase II
460 // 6 CPX_IT_LIM_INFEAS
461 // Iteration limit exceeded in Phase I
462 // 7 CPX_TIME_LIM_FEAS
463 // Time limit exceeded in Phase II
464 // 8 CPX_TIME_LIM_INFEAS
465 // Time limit exceeded in Phase I
466 // 9 CPX_NUM_BEST_FEAS
467 // Problem non-optimal, singularities in Phase II
468 // 10 CPX_NUM_BEST_INFEAS
469 // Problem non-optimal, singularities in Phase I
470 // 11 CPX_OPTIMAL_INFEAS
471 // Optimal solution found, unscaled infeasibilities
473 // Aborted in Phase II
474 // 13 CPX_ABORT_INFEAS
475 // Aborted in Phase I
476 // 14 CPX_ABORT_DUAL_INFEAS
477 // Aborted in barrier, dual infeasible
478 // 15 CPX_ABORT_PRIM_INFEAS
479 // Aborted in barrier, primal infeasible
480 // 16 CPX_ABORT_PRIM_DUAL_INFEAS
481 // Aborted in barrier, primal and dual infeasible
482 // 17 CPX_ABORT_PRIM_DUAL_FEAS
483 // Aborted in barrier, primal and dual feasible
484 // 18 CPX_ABORT_CROSSOVER
485 // Aborted in crossover
487 // Infeasible or unbounded
491 // Ezeket hova tegyem:
492 // ??case CPX_ABORT_DUAL_INFEAS
493 // ??case CPX_ABORT_CROSSOVER
494 // ??case CPX_INForUNBD
497 //Some more interesting stuff:
499 // CPX_PARAM_LPMETHOD 1062 int LPMETHOD
504 // 4 Standard Barrier
506 // Description: Method for linear optimization.
507 // 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
508 #if CPX_VERSION < 900
509 void statusSwitch(CPXENVptr env,int& stat){
511 CPXgetintparam (env,CPX_PARAM_LPMETHOD,&lpmethod);
513 if (stat==CPX_UNBOUNDED){
517 if (stat==CPX_INFEASIBLE)
523 void statusSwitch(CPXENVptr,int&){}
526 LpCplex::SolutionStatus LpCplex::_getPrimalStatus() const
528 //Unboundedness not treated well: the following is from cplex 9.0 doc
529 // About Unboundedness
531 // The treatment of models that are unbounded involves a few
532 // subtleties. Specifically, a declaration of unboundedness means that
533 // ILOG CPLEX has determined that the model has an unbounded
534 // ray. Given any feasible solution x with objective z, a multiple of
535 // the unbounded ray can be added to x to give a feasible solution
536 // with objective z-1 (or z+1 for maximization models). Thus, if a
537 // feasible solution exists, then the optimal objective is
538 // unbounded. Note that ILOG CPLEX has not necessarily concluded that
539 // a feasible solution exists. Users can call the routine CPXsolninfo
540 // to determine whether ILOG CPLEX has also concluded that the model
541 // has a feasible solution.
543 int stat = CPXgetstat(env, lp);
544 #if CPX_VERSION >= 800
547 case CPX_STAT_OPTIMAL:
549 case CPX_STAT_UNBOUNDED:
551 case CPX_STAT_INFEASIBLE:
557 statusSwitch(env,stat);
558 //CPXgetstat(env, lp);
559 //printf("A primal status: %d, CPX_OPTIMAL=%d \n",stat,CPX_OPTIMAL);
562 return UNDEFINED; //Undefined
563 case CPX_OPTIMAL://Optimal
565 case CPX_UNBOUNDED://Unbounded
566 return INFEASIBLE;//In case of dual simplex
568 case CPX_INFEASIBLE://Infeasible
569 // case CPX_IT_LIM_INFEAS:
570 // case CPX_TIME_LIM_INFEAS:
571 // case CPX_NUM_BEST_INFEAS:
572 // case CPX_OPTIMAL_INFEAS:
573 // case CPX_ABORT_INFEAS:
574 // case CPX_ABORT_PRIM_INFEAS:
575 // case CPX_ABORT_PRIM_DUAL_INFEAS:
576 return INFINITE;//In case of dual simplex
579 // case CPX_IT_LIM_FEAS:
580 // case CPX_TIME_LIM_FEAS:
581 // case CPX_NUM_BEST_FEAS:
582 // case CPX_ABORT_FEAS:
583 // case CPX_ABORT_PRIM_DUAL_FEAS:
586 return UNDEFINED; //Everything else comes here
592 //9.0-as cplex verzio statusai
593 // CPX_STAT_ABORT_DUAL_OBJ_LIM
594 // CPX_STAT_ABORT_IT_LIM
595 // CPX_STAT_ABORT_OBJ_LIM
596 // CPX_STAT_ABORT_PRIM_OBJ_LIM
597 // CPX_STAT_ABORT_TIME_LIM
598 // CPX_STAT_ABORT_USER
599 // CPX_STAT_FEASIBLE_RELAXED
600 // CPX_STAT_INFEASIBLE
601 // CPX_STAT_INForUNBD
604 // CPX_STAT_OPTIMAL_FACE_UNBOUNDED
605 // CPX_STAT_OPTIMAL_INFEAS
606 // CPX_STAT_OPTIMAL_RELAXED
607 // CPX_STAT_UNBOUNDED
609 LpCplex::SolutionStatus LpCplex::_getDualStatus() const
611 int stat = CPXgetstat(env, lp);
612 #if CPX_VERSION >= 800
615 case CPX_STAT_OPTIMAL:
617 case CPX_STAT_UNBOUNDED:
623 statusSwitch(env,stat);
626 return UNDEFINED; //Undefined
627 case CPX_OPTIMAL://Optimal
632 return UNDEFINED; //Everything else comes here
638 LpCplex::ProblemTypes LpCplex::_getProblemType() const
640 int stat = CPXgetstat(env, lp);
641 #if CPX_VERSION >= 800
644 case CPX_STAT_OPTIMAL:
645 return PRIMAL_DUAL_FEASIBLE;
646 case CPX_STAT_UNBOUNDED:
647 return PRIMAL_FEASIBLE_DUAL_INFEASIBLE;
653 case CPX_OPTIMAL://Optimal
654 return PRIMAL_DUAL_FEASIBLE;
656 return PRIMAL_FEASIBLE_DUAL_INFEASIBLE;
657 // return PRIMAL_INFEASIBLE_DUAL_FEASIBLE;
658 // return PRIMAL_DUAL_INFEASIBLE;
660 //Seems to be that this is all we can say for sure
669 void LpCplex::_setMax()
671 CPXchgobjsen(env, lp, CPX_MAX);
673 void LpCplex::_setMin()
675 CPXchgobjsen(env, lp, CPX_MIN);
678 bool LpCplex::_isMax() const
680 if (CPXgetobjsen(env, lp)==CPX_MAX)