3 * This file is a part of LEMON, a generic C++ optimization library
5 * Copyright (C) 2003-2006
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
20 #include<lemon/lp_cplex.h>
23 ///\brief Implementation of the LEMON-CPLEX lp solver interface.
26 LpCplex::LpCplex() : LpSolverBase() {
28 // env = CPXopenCPLEXdevelop(&status);
29 env = CPXopenCPLEX(&status);
30 lp = CPXcreateprob(env, &status, "LP problem");
38 LpSolverBase &LpCplex::_newLp()
40 //The first approach opens a new environment
41 LpCplex* newlp=new LpCplex();
45 LpSolverBase &LpCplex::_copyLp() {
46 ///\bug FixID data is not copied!
47 //The first approach opens a new environment
48 LpCplex* newlp=new LpCplex();
49 //The routine CPXcloneprob can be used to create a new CPLEX problem
50 //object and copy all the problem data from an existing problem
51 //object to it. Solution and starting information is not copied.
52 newlp->lp = CPXcloneprob(env, lp, &status);
56 int LpCplex::_addCol()
58 int i = CPXgetnumcols(env, lp);
60 lb[0]=-INF;//-CPX_INFBOUND;
61 ub[0]=INF;//CPX_INFBOUND;
62 status = CPXnewcols(env, lp, 1, NULL, lb, ub, NULL, NULL);
67 int LpCplex::_addRow()
69 //We want a row that is not constrained
71 sense[0]='L';//<= constraint
74 int i = CPXgetnumrows(env, lp);
75 status = CPXnewrows(env, lp, 1, rhs, sense, NULL, NULL);
80 void LpCplex::_eraseCol(int i) {
81 CPXdelcols(env, lp, i, i);
84 void LpCplex::_eraseRow(int i) {
85 CPXdelrows(env, lp, i, i);
88 void LpCplex::_getColName(int col, std::string &name)
92 CPXgetcolname(env, lp, 0, 0, 0, &storespace, col, col);
98 ///\bug return code unchecked for error
99 CPXgetcolname(env, lp, names, buf, storespace, &dontcare, col, col);
103 void LpCplex::_setColName(int col, const std::string &name)
107 names[0] = const_cast<char*>(name.c_str());
108 ///\bug return code unchecked for error
109 CPXchgcolname(env, lp, 1, &col, names);
112 ///\warning Data at index 0 is ignored in the arrays.
113 void LpCplex::_setRowCoeffs(int i, LpRowIterator b, LpRowIterator e)
115 std::vector<int> indices;
116 std::vector<int> rowlist;
117 std::vector<Value> values;
119 for(LpRowIterator it=b; it!=e; ++it) {
120 indices.push_back(it->first);
121 values.push_back(it->second);
122 rowlist.push_back(i);
125 status = CPXchgcoeflist(env, lp, values.size(),
126 &rowlist[0], &indices[0], &values[0]);
129 void LpCplex::_setColCoeffs(int i, LpColIterator b, LpColIterator e)
131 std::vector<int> indices;
132 std::vector<int> collist;
133 std::vector<Value> values;
135 for(LpColIterator it=b; it!=e; ++it) {
136 indices.push_back(it->first);
137 values.push_back(it->second);
138 collist.push_back(i);
141 status = CPXchgcoeflist(env, lp, values.size(),
142 &indices[0], &collist[0], &values[0]);
145 void LpCplex::_setCoeff(int row, int col, Value value)
147 CPXchgcoef(env, lp, row, col, value);
150 LpCplex::Value LpCplex::_getCoeff(int row, int col)
152 LpCplex::Value value;
153 CPXgetcoef(env, lp, row, col, &value);
157 void LpCplex::_setColLowerBound(int i, Value value)
165 status = CPXchgbds(env, lp, 1, indices, lu, bd);
169 LpCplex::Value LpCplex::_getColLowerBound(int i)
172 CPXgetlb (env, lp, &x, i, i);
176 void LpCplex::_setColUpperBound(int i, Value value)
184 status = CPXchgbds(env, lp, 1, indices, lu, bd);
187 LpCplex::Value LpCplex::_getColUpperBound(int i)
190 CPXgetub (env, lp, &x, i, i);
194 //This will be easier to implement
195 void LpCplex::_setRowBounds(int i, Value lb, Value ub)
198 if (lb==INF || ub==-INF) {
209 CPXchgsense(env, lp, cnt, indices, sense);
210 CPXchgcoef(env, lp, i, -1, ub);
216 CPXchgsense(env, lp, cnt, indices, sense);
217 CPXchgcoef(env, lp, i, -1, lb);
222 CPXchgsense(env, lp, cnt, indices, sense);
223 CPXchgcoef(env, lp, i, -1, lb);
227 CPXchgsense(env, lp, cnt, indices, sense);
228 CPXchgcoef(env, lp, i, -1, lb);
229 CPXchgcoef(env, lp, i, -2, ub-lb);
235 // void LpCplex::_setRowLowerBound(int i, Value value)
237 // //Not implemented, obsolete
240 // void LpCplex::_setRowUpperBound(int i, Value value)
242 // //Not implemented, obsolete
243 // // //TODO Ezt kell meg megirni
244 // // //type of the problem
246 // // status = CPXgetsense(env, lp, sense, i, i);
248 // // status = CPXgetrhs(env, lp, rhs, i, i);
250 // // switch (sense[0]) {
251 // // case 'L'://<= constraint
253 // // case 'E'://= constraint
255 // // case 'G'://>= constraint
257 // // case 'R'://ranged constraint
263 // // status = CPXchgcoef(env, lp, i, -2, value_rng);
266 void LpCplex::_getRowBounds(int i, Value &lb, Value &ub)
269 CPXgetsense(env, lp, &sense,i,i);
275 CPXgetcoef(env, lp, i, -1, &ub);
278 CPXgetcoef(env, lp, i, -1, &lb);
281 CPXgetcoef(env, lp, i, -1, &lb);
285 CPXgetcoef(env, lp, i, -1, &lb);
287 CPXgetcoef(env, lp, i, -2, &x);
293 void LpCplex::_setObjCoeff(int i, Value obj_coef)
295 CPXchgcoef(env, lp, -1, i, obj_coef);
298 LpCplex::Value LpCplex::_getObjCoeff(int i)
301 CPXgetcoef(env, lp, -1, i, &x);
305 void LpCplex::_clearObj()
307 for (int i=0;i< CPXgetnumcols(env, lp);++i){
308 CPXchgcoef(env, lp, -1, i, 0);
312 // The routine returns zero unless an error occurred during the
313 // optimization. Examples of errors include exhausting available
314 // memory (CPXERR_NO_MEMORY) or encountering invalid data in the
315 // CPLEX problem object (CPXERR_NO_PROBLEM). Exceeding a
316 // user-specified CPLEX limit, or proving the model infeasible or
317 // unbounded, are not considered errors. Note that a zero return
318 // value does not necessarily mean that a solution exists. Use query
319 // routines CPXsolninfo, CPXgetstat, and CPXsolution to obtain
320 // further information about the status of the optimization.
321 LpCplex::SolveExitStatus LpCplex::_solve()
324 status = CPXlpopt(env, lp);
325 //status = CPXprimopt(env, lp);
326 #if CPX_VERSION >= 800
333 switch (CPXgetstat(env, lp))
335 case CPX_STAT_OPTIMAL:
336 case CPX_STAT_INFEASIBLE:
337 case CPX_STAT_UNBOUNDED:
345 //We want to exclude some cases
346 switch (CPXgetstat(env, lp)){
348 case CPX_IT_LIM_FEAS:
349 case CPX_IT_LIM_INFEAS:
350 case CPX_TIME_LIM_FEAS:
351 case CPX_TIME_LIM_INFEAS:
363 LpCplex::Value LpCplex::_getPrimal(int i)
366 CPXgetx(env, lp, &x, i, i);
370 LpCplex::Value LpCplex::_getDual(int i)
373 CPXgetpi(env, lp, &y, i, i);
377 LpCplex::Value LpCplex::_getPrimalValue()
380 //method = CPXgetmethod (env, lp);
381 //printf("CPXgetprobtype %d \n",CPXgetprobtype(env,lp));
382 status = CPXgetobjval(env, lp, &objval);
383 //printf("Objective value: %g \n",objval);
386 bool LpCplex::_isBasicCol(int i) {
387 int cstat[CPXgetnumcols(env, lp)];
388 CPXgetbase(env, lp, cstat, NULL);
389 return (cstat[i]==CPX_BASIC);
392 //7.5-os cplex statusai (Vigyazat: a 9.0-asei masok!)
393 // 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.
395 // For Simplex, Barrier
397 // Optimal solution found
399 // Problem infeasible
403 // Objective limit exceeded in Phase II
405 // Iteration limit exceeded in Phase II
406 // 6 CPX_IT_LIM_INFEAS
407 // Iteration limit exceeded in Phase I
408 // 7 CPX_TIME_LIM_FEAS
409 // Time limit exceeded in Phase II
410 // 8 CPX_TIME_LIM_INFEAS
411 // Time limit exceeded in Phase I
412 // 9 CPX_NUM_BEST_FEAS
413 // Problem non-optimal, singularities in Phase II
414 // 10 CPX_NUM_BEST_INFEAS
415 // Problem non-optimal, singularities in Phase I
416 // 11 CPX_OPTIMAL_INFEAS
417 // Optimal solution found, unscaled infeasibilities
419 // Aborted in Phase II
420 // 13 CPX_ABORT_INFEAS
421 // Aborted in Phase I
422 // 14 CPX_ABORT_DUAL_INFEAS
423 // Aborted in barrier, dual infeasible
424 // 15 CPX_ABORT_PRIM_INFEAS
425 // Aborted in barrier, primal infeasible
426 // 16 CPX_ABORT_PRIM_DUAL_INFEAS
427 // Aborted in barrier, primal and dual infeasible
428 // 17 CPX_ABORT_PRIM_DUAL_FEAS
429 // Aborted in barrier, primal and dual feasible
430 // 18 CPX_ABORT_CROSSOVER
431 // Aborted in crossover
433 // Infeasible or unbounded
437 // Ezeket hova tegyem:
438 // ??case CPX_ABORT_DUAL_INFEAS
439 // ??case CPX_ABORT_CROSSOVER
440 // ??case CPX_INForUNBD
443 //Some more interesting stuff:
445 // CPX_PARAM_LPMETHOD 1062 int LPMETHOD
450 // 4 Standard Barrier
452 // Description: Method for linear optimization.
453 // 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
455 void statusSwitch(CPXENVptr env,int& stat){
456 #if CPX_VERSION < 900
458 CPXgetintparam (env,CPX_PARAM_LPMETHOD,&lpmethod);
460 if (stat==CPX_UNBOUNDED){
464 if (stat==CPX_INFEASIBLE)
471 LpCplex::SolutionStatus LpCplex::_getPrimalStatus()
473 //Unboundedness not treated well: the following is from cplex 9.0 doc
474 // About Unboundedness
476 // The treatment of models that are unbounded involves a few
477 // subtleties. Specifically, a declaration of unboundedness means that
478 // ILOG CPLEX has determined that the model has an unbounded
479 // ray. Given any feasible solution x with objective z, a multiple of
480 // the unbounded ray can be added to x to give a feasible solution
481 // with objective z-1 (or z+1 for maximization models). Thus, if a
482 // feasible solution exists, then the optimal objective is
483 // unbounded. Note that ILOG CPLEX has not necessarily concluded that
484 // a feasible solution exists. Users can call the routine CPXsolninfo
485 // to determine whether ILOG CPLEX has also concluded that the model
486 // has a feasible solution.
488 int stat = CPXgetstat(env, lp);
489 #if CPX_VERSION >= 800
492 case CPX_STAT_OPTIMAL:
494 case CPX_STAT_UNBOUNDED:
496 case CPX_STAT_INFEASIBLE:
502 statusSwitch(env,stat);
503 //CPXgetstat(env, lp);
504 //printf("A primal status: %d, CPX_OPTIMAL=%d \n",stat,CPX_OPTIMAL);
507 return UNDEFINED; //Undefined
508 case CPX_OPTIMAL://Optimal
510 case CPX_UNBOUNDED://Unbounded
511 return INFEASIBLE;//In case of dual simplex
513 case CPX_INFEASIBLE://Infeasible
514 // case CPX_IT_LIM_INFEAS:
515 // case CPX_TIME_LIM_INFEAS:
516 // case CPX_NUM_BEST_INFEAS:
517 // case CPX_OPTIMAL_INFEAS:
518 // case CPX_ABORT_INFEAS:
519 // case CPX_ABORT_PRIM_INFEAS:
520 // case CPX_ABORT_PRIM_DUAL_INFEAS:
521 return INFINITE;//In case of dual simplex
524 // case CPX_IT_LIM_FEAS:
525 // case CPX_TIME_LIM_FEAS:
526 // case CPX_NUM_BEST_FEAS:
527 // case CPX_ABORT_FEAS:
528 // case CPX_ABORT_PRIM_DUAL_FEAS:
531 return UNDEFINED; //Everything else comes here
537 //9.0-as cplex verzio statusai
538 // CPX_STAT_ABORT_DUAL_OBJ_LIM
539 // CPX_STAT_ABORT_IT_LIM
540 // CPX_STAT_ABORT_OBJ_LIM
541 // CPX_STAT_ABORT_PRIM_OBJ_LIM
542 // CPX_STAT_ABORT_TIME_LIM
543 // CPX_STAT_ABORT_USER
544 // CPX_STAT_FEASIBLE_RELAXED
545 // CPX_STAT_INFEASIBLE
546 // CPX_STAT_INForUNBD
549 // CPX_STAT_OPTIMAL_FACE_UNBOUNDED
550 // CPX_STAT_OPTIMAL_INFEAS
551 // CPX_STAT_OPTIMAL_RELAXED
552 // CPX_STAT_UNBOUNDED
554 LpCplex::SolutionStatus LpCplex::_getDualStatus()
556 int stat = CPXgetstat(env, lp);
557 #if CPX_VERSION >= 800
560 case CPX_STAT_OPTIMAL:
562 case CPX_STAT_UNBOUNDED:
568 statusSwitch(env,stat);
571 return UNDEFINED; //Undefined
572 case CPX_OPTIMAL://Optimal
577 return UNDEFINED; //Everything else comes here
583 LpCplex::ProblemTypes LpCplex::_getProblemType()
585 int stat = CPXgetstat(env, lp);
586 #if CPX_VERSION >= 800
589 case CPX_STAT_OPTIMAL:
590 return PRIMAL_DUAL_FEASIBLE;
591 case CPX_STAT_UNBOUNDED:
592 return PRIMAL_FEASIBLE_DUAL_INFEASIBLE;
598 case CPX_OPTIMAL://Optimal
599 return PRIMAL_DUAL_FEASIBLE;
601 return PRIMAL_FEASIBLE_DUAL_INFEASIBLE;
602 // return PRIMAL_INFEASIBLE_DUAL_FEASIBLE;
603 // return PRIMAL_DUAL_INFEASIBLE;
605 //Seems to be that this is all we can say for sure
614 void LpCplex::_setMax()
616 CPXchgobjsen(env, lp, CPX_MAX);
618 void LpCplex::_setMin()
620 CPXchgobjsen(env, lp, CPX_MIN);
623 bool LpCplex::_isMax()
625 if (CPXgetobjsen(env, lp)==CPX_MAX)