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() {
27 // env = CPXopenCPLEXdevelop(&status);
28 env = CPXopenCPLEX(&status);
29 lp = CPXcreateprob(env, &status, "LP problem");
37 LpSolverBase &LpCplex::_newLp()
39 //The first approach opens a new environment
40 LpCplex* newlp=new LpCplex();
44 LpSolverBase &LpCplex::_copyLp() {
45 ///\bug FixID data is not copied!
46 //The first approach opens a new environment
47 LpCplex* newlp=new LpCplex();
48 //The routine CPXcloneprob can be used to create a new CPLEX problem
49 //object and copy all the problem data from an existing problem
50 //object to it. Solution and starting information is not copied.
51 newlp->lp = CPXcloneprob(env, lp, &status);
55 int LpCplex::_addCol()
57 int i = CPXgetnumcols(env, lp);
59 lb[0]=-INF;//-CPX_INFBOUND;
60 ub[0]=INF;//CPX_INFBOUND;
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)
91 CPXgetcolname(env, lp, 0, 0, 0, &storespace, col, col);
97 ///\bug return code unchecked for error
98 CPXgetcolname(env, lp, names, buf, storespace, &dontcare, col, col);
102 void LpCplex::_setColName(int col, const std::string &name)
106 names[0] = const_cast<char*>(name.c_str());
107 ///\bug return code unchecked for error
108 CPXchgcolname(env, lp, 1, &col, names);
111 ///\warning Data at index 0 is ignored in the arrays.
112 void LpCplex::_setRowCoeffs(int i, ConstRowIterator b, ConstRowIterator e)
114 std::vector<int> indices;
115 std::vector<int> rowlist;
116 std::vector<Value> values;
118 for(ConstRowIterator it=b; it!=e; ++it) {
119 indices.push_back(it->first);
120 values.push_back(it->second);
121 rowlist.push_back(i);
124 status = CPXchgcoeflist(env, lp, values.size(),
125 &rowlist[0], &indices[0], &values[0]);
128 void LpSoplex::_getRowCoeffs(int i, RowIterator b) {
132 void LpCplex::_setColCoeffs(int i, ConstColIterator b, ConstColIterator e)
134 std::vector<int> indices;
135 std::vector<int> collist;
136 std::vector<Value> values;
138 for(ConstColIterator it=b; it!=e; ++it) {
139 indices.push_back(it->first);
140 values.push_back(it->second);
141 collist.push_back(i);
144 status = CPXchgcoeflist(env, lp, values.size(),
145 &indices[0], &collist[0], &values[0]);
148 void LpSoplex::_getColCoeffs(int i, ColIterator b) {
152 void LpCplex::_setCoeff(int row, int col, Value value)
154 CPXchgcoef(env, lp, row, col, value);
157 LpCplex::Value LpCplex::_getCoeff(int row, int col)
159 LpCplex::Value value;
160 CPXgetcoef(env, lp, row, col, &value);
164 void LpCplex::_setColLowerBound(int i, Value value)
172 status = CPXchgbds(env, lp, 1, indices, lu, bd);
176 LpCplex::Value LpCplex::_getColLowerBound(int i)
179 CPXgetlb (env, lp, &x, i, i);
183 void LpCplex::_setColUpperBound(int i, Value value)
191 status = CPXchgbds(env, lp, 1, indices, lu, bd);
194 LpCplex::Value LpCplex::_getColUpperBound(int i)
197 CPXgetub (env, lp, &x, i, i);
201 //This will be easier to implement
202 void LpCplex::_setRowBounds(int i, Value lb, Value ub)
205 if (lb==INF || ub==-INF) {
216 CPXchgsense(env, lp, cnt, indices, sense);
217 CPXchgcoef(env, lp, i, -1, ub);
223 CPXchgsense(env, lp, cnt, indices, sense);
224 CPXchgcoef(env, lp, i, -1, lb);
229 CPXchgsense(env, lp, cnt, indices, sense);
230 CPXchgcoef(env, lp, i, -1, lb);
234 CPXchgsense(env, lp, cnt, indices, sense);
235 CPXchgcoef(env, lp, i, -1, lb);
236 CPXchgcoef(env, lp, i, -2, ub-lb);
242 // void LpCplex::_setRowLowerBound(int i, Value value)
244 // //Not implemented, obsolete
247 // void LpCplex::_setRowUpperBound(int i, Value value)
249 // //Not implemented, obsolete
250 // // //TODO Ezt kell meg megirni
251 // // //type of the problem
253 // // status = CPXgetsense(env, lp, sense, i, i);
255 // // status = CPXgetrhs(env, lp, rhs, i, i);
257 // // switch (sense[0]) {
258 // // case 'L'://<= constraint
260 // // case 'E'://= constraint
262 // // case 'G'://>= constraint
264 // // case 'R'://ranged constraint
270 // // status = CPXchgcoef(env, lp, i, -2, value_rng);
273 void LpCplex::_getRowBounds(int i, Value &lb, Value &ub)
276 CPXgetsense(env, lp, &sense,i,i);
282 CPXgetcoef(env, lp, i, -1, &ub);
285 CPXgetcoef(env, lp, i, -1, &lb);
288 CPXgetcoef(env, lp, i, -1, &lb);
292 CPXgetcoef(env, lp, i, -1, &lb);
294 CPXgetcoef(env, lp, i, -2, &x);
300 void LpCplex::_setObjCoeff(int i, Value obj_coef)
302 CPXchgcoef(env, lp, -1, i, obj_coef);
305 LpCplex::Value LpCplex::_getObjCoeff(int i)
308 CPXgetcoef(env, lp, -1, i, &x);
312 void LpCplex::_clearObj()
314 for (int i=0;i< CPXgetnumcols(env, lp);++i){
315 CPXchgcoef(env, lp, -1, i, 0);
319 // The routine returns zero unless an error occurred during the
320 // optimization. Examples of errors include exhausting available
321 // memory (CPXERR_NO_MEMORY) or encountering invalid data in the
322 // CPLEX problem object (CPXERR_NO_PROBLEM). Exceeding a
323 // user-specified CPLEX limit, or proving the model infeasible or
324 // unbounded, are not considered errors. Note that a zero return
325 // value does not necessarily mean that a solution exists. Use query
326 // routines CPXsolninfo, CPXgetstat, and CPXsolution to obtain
327 // further information about the status of the optimization.
328 LpCplex::SolveExitStatus LpCplex::_solve()
331 status = CPXlpopt(env, lp);
332 //status = CPXprimopt(env, lp);
333 #if CPX_VERSION >= 800
340 switch (CPXgetstat(env, lp))
342 case CPX_STAT_OPTIMAL:
343 case CPX_STAT_INFEASIBLE:
344 case CPX_STAT_UNBOUNDED:
352 //We want to exclude some cases
353 switch (CPXgetstat(env, lp)){
355 case CPX_IT_LIM_FEAS:
356 case CPX_IT_LIM_INFEAS:
357 case CPX_TIME_LIM_FEAS:
358 case CPX_TIME_LIM_INFEAS:
370 LpCplex::Value LpCplex::_getPrimal(int i)
373 CPXgetx(env, lp, &x, i, i);
377 LpCplex::Value LpCplex::_getDual(int i)
380 CPXgetpi(env, lp, &y, i, i);
384 LpCplex::Value LpCplex::_getPrimalValue()
387 //method = CPXgetmethod (env, lp);
388 //printf("CPXgetprobtype %d \n",CPXgetprobtype(env,lp));
389 status = CPXgetobjval(env, lp, &objval);
390 //printf("Objective value: %g \n",objval);
393 bool LpCplex::_isBasicCol(int i) {
394 int cstat[CPXgetnumcols(env, lp)];
395 CPXgetbase(env, lp, cstat, NULL);
396 return (cstat[i]==CPX_BASIC);
399 //7.5-os cplex statusai (Vigyazat: a 9.0-asei masok!)
400 // 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.
402 // For Simplex, Barrier
404 // Optimal solution found
406 // Problem infeasible
410 // Objective limit exceeded in Phase II
412 // Iteration limit exceeded in Phase II
413 // 6 CPX_IT_LIM_INFEAS
414 // Iteration limit exceeded in Phase I
415 // 7 CPX_TIME_LIM_FEAS
416 // Time limit exceeded in Phase II
417 // 8 CPX_TIME_LIM_INFEAS
418 // Time limit exceeded in Phase I
419 // 9 CPX_NUM_BEST_FEAS
420 // Problem non-optimal, singularities in Phase II
421 // 10 CPX_NUM_BEST_INFEAS
422 // Problem non-optimal, singularities in Phase I
423 // 11 CPX_OPTIMAL_INFEAS
424 // Optimal solution found, unscaled infeasibilities
426 // Aborted in Phase II
427 // 13 CPX_ABORT_INFEAS
428 // Aborted in Phase I
429 // 14 CPX_ABORT_DUAL_INFEAS
430 // Aborted in barrier, dual infeasible
431 // 15 CPX_ABORT_PRIM_INFEAS
432 // Aborted in barrier, primal infeasible
433 // 16 CPX_ABORT_PRIM_DUAL_INFEAS
434 // Aborted in barrier, primal and dual infeasible
435 // 17 CPX_ABORT_PRIM_DUAL_FEAS
436 // Aborted in barrier, primal and dual feasible
437 // 18 CPX_ABORT_CROSSOVER
438 // Aborted in crossover
440 // Infeasible or unbounded
444 // Ezeket hova tegyem:
445 // ??case CPX_ABORT_DUAL_INFEAS
446 // ??case CPX_ABORT_CROSSOVER
447 // ??case CPX_INForUNBD
450 //Some more interesting stuff:
452 // CPX_PARAM_LPMETHOD 1062 int LPMETHOD
457 // 4 Standard Barrier
459 // Description: Method for linear optimization.
460 // 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
462 void statusSwitch(CPXENVptr env,int& stat){
463 #if CPX_VERSION < 900
465 CPXgetintparam (env,CPX_PARAM_LPMETHOD,&lpmethod);
467 if (stat==CPX_UNBOUNDED){
471 if (stat==CPX_INFEASIBLE)
478 LpCplex::SolutionStatus LpCplex::_getPrimalStatus()
480 //Unboundedness not treated well: the following is from cplex 9.0 doc
481 // About Unboundedness
483 // The treatment of models that are unbounded involves a few
484 // subtleties. Specifically, a declaration of unboundedness means that
485 // ILOG CPLEX has determined that the model has an unbounded
486 // ray. Given any feasible solution x with objective z, a multiple of
487 // the unbounded ray can be added to x to give a feasible solution
488 // with objective z-1 (or z+1 for maximization models). Thus, if a
489 // feasible solution exists, then the optimal objective is
490 // unbounded. Note that ILOG CPLEX has not necessarily concluded that
491 // a feasible solution exists. Users can call the routine CPXsolninfo
492 // to determine whether ILOG CPLEX has also concluded that the model
493 // has a feasible solution.
495 int stat = CPXgetstat(env, lp);
496 #if CPX_VERSION >= 800
499 case CPX_STAT_OPTIMAL:
501 case CPX_STAT_UNBOUNDED:
503 case CPX_STAT_INFEASIBLE:
509 statusSwitch(env,stat);
510 //CPXgetstat(env, lp);
511 //printf("A primal status: %d, CPX_OPTIMAL=%d \n",stat,CPX_OPTIMAL);
514 return UNDEFINED; //Undefined
515 case CPX_OPTIMAL://Optimal
517 case CPX_UNBOUNDED://Unbounded
518 return INFEASIBLE;//In case of dual simplex
520 case CPX_INFEASIBLE://Infeasible
521 // case CPX_IT_LIM_INFEAS:
522 // case CPX_TIME_LIM_INFEAS:
523 // case CPX_NUM_BEST_INFEAS:
524 // case CPX_OPTIMAL_INFEAS:
525 // case CPX_ABORT_INFEAS:
526 // case CPX_ABORT_PRIM_INFEAS:
527 // case CPX_ABORT_PRIM_DUAL_INFEAS:
528 return INFINITE;//In case of dual simplex
531 // case CPX_IT_LIM_FEAS:
532 // case CPX_TIME_LIM_FEAS:
533 // case CPX_NUM_BEST_FEAS:
534 // case CPX_ABORT_FEAS:
535 // case CPX_ABORT_PRIM_DUAL_FEAS:
538 return UNDEFINED; //Everything else comes here
544 //9.0-as cplex verzio statusai
545 // CPX_STAT_ABORT_DUAL_OBJ_LIM
546 // CPX_STAT_ABORT_IT_LIM
547 // CPX_STAT_ABORT_OBJ_LIM
548 // CPX_STAT_ABORT_PRIM_OBJ_LIM
549 // CPX_STAT_ABORT_TIME_LIM
550 // CPX_STAT_ABORT_USER
551 // CPX_STAT_FEASIBLE_RELAXED
552 // CPX_STAT_INFEASIBLE
553 // CPX_STAT_INForUNBD
556 // CPX_STAT_OPTIMAL_FACE_UNBOUNDED
557 // CPX_STAT_OPTIMAL_INFEAS
558 // CPX_STAT_OPTIMAL_RELAXED
559 // CPX_STAT_UNBOUNDED
561 LpCplex::SolutionStatus LpCplex::_getDualStatus()
563 int stat = CPXgetstat(env, lp);
564 #if CPX_VERSION >= 800
567 case CPX_STAT_OPTIMAL:
569 case CPX_STAT_UNBOUNDED:
575 statusSwitch(env,stat);
578 return UNDEFINED; //Undefined
579 case CPX_OPTIMAL://Optimal
584 return UNDEFINED; //Everything else comes here
590 LpCplex::ProblemTypes LpCplex::_getProblemType()
592 int stat = CPXgetstat(env, lp);
593 #if CPX_VERSION >= 800
596 case CPX_STAT_OPTIMAL:
597 return PRIMAL_DUAL_FEASIBLE;
598 case CPX_STAT_UNBOUNDED:
599 return PRIMAL_FEASIBLE_DUAL_INFEASIBLE;
605 case CPX_OPTIMAL://Optimal
606 return PRIMAL_DUAL_FEASIBLE;
608 return PRIMAL_FEASIBLE_DUAL_INFEASIBLE;
609 // return PRIMAL_INFEASIBLE_DUAL_FEASIBLE;
610 // return PRIMAL_DUAL_INFEASIBLE;
612 //Seems to be that this is all we can say for sure
621 void LpCplex::_setMax()
623 CPXchgobjsen(env, lp, CPX_MAX);
625 void LpCplex::_setMin()
627 CPXchgobjsen(env, lp, CPX_MIN);
630 bool LpCplex::_isMax()
632 if (CPXgetobjsen(env, lp)==CPX_MAX)