3 * This file is a part of LEMON, a generic C++ optimization library
5 * Copyright (C) 2003-2007
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) const
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 int LpCplex::_colByName(const std::string& name) const
114 if (CPXgetcolindex(env, lp,
115 const_cast<char*>(name.c_str()), &index) == 0) {
121 ///\warning Data at index 0 is ignored in the arrays.
122 void LpCplex::_setRowCoeffs(int i, ConstRowIterator b, ConstRowIterator e)
124 std::vector<int> indices;
125 std::vector<int> rowlist;
126 std::vector<Value> values;
128 for(ConstRowIterator it=b; it!=e; ++it) {
129 indices.push_back(it->first);
130 values.push_back(it->second);
131 rowlist.push_back(i);
134 status = CPXchgcoeflist(env, lp, values.size(),
135 &rowlist[0], &indices[0], &values[0]);
138 void LpSoplex::_getRowCoeffs(int i, RowIterator b) const {
142 void LpCplex::_setColCoeffs(int i, ConstColIterator b, ConstColIterator e)
144 std::vector<int> indices;
145 std::vector<int> collist;
146 std::vector<Value> values;
148 for(ConstColIterator it=b; it!=e; ++it) {
149 indices.push_back(it->first);
150 values.push_back(it->second);
151 collist.push_back(i);
154 status = CPXchgcoeflist(env, lp, values.size(),
155 &indices[0], &collist[0], &values[0]);
158 void LpSoplex::_getColCoeffs(int i, ColIterator b) const {
162 void LpCplex::_setCoeff(int row, int col, Value value)
164 CPXchgcoef(env, lp, row, col, value);
167 LpCplex::Value LpCplex::_getCoeff(int row, int col) const
169 LpCplex::Value value;
170 CPXgetcoef(env, lp, row, col, &value);
174 void LpCplex::_setColLowerBound(int i, Value value)
182 status = CPXchgbds(env, lp, 1, indices, lu, bd);
186 LpCplex::Value LpCplex::_getColLowerBound(int i) const
189 CPXgetlb (env, lp, &x, i, i);
193 void LpCplex::_setColUpperBound(int i, Value value)
201 status = CPXchgbds(env, lp, 1, indices, lu, bd);
204 LpCplex::Value LpCplex::_getColUpperBound(int i) const
207 CPXgetub (env, lp, &x, i, i);
211 //This will be easier to implement
212 void LpCplex::_setRowBounds(int i, Value lb, Value ub)
215 if (lb==INF || ub==-INF) {
226 CPXchgsense(env, lp, cnt, indices, sense);
227 CPXchgcoef(env, lp, i, -1, ub);
233 CPXchgsense(env, lp, cnt, indices, sense);
234 CPXchgcoef(env, lp, i, -1, lb);
239 CPXchgsense(env, lp, cnt, indices, sense);
240 CPXchgcoef(env, lp, i, -1, lb);
244 CPXchgsense(env, lp, cnt, indices, sense);
245 CPXchgcoef(env, lp, i, -1, lb);
246 CPXchgcoef(env, lp, i, -2, ub-lb);
252 // void LpCplex::_setRowLowerBound(int i, Value value)
254 // //Not implemented, obsolete
257 // void LpCplex::_setRowUpperBound(int i, Value value)
259 // //Not implemented, obsolete
260 // // //TODO Ezt kell meg megirni
261 // // //type of the problem
263 // // status = CPXgetsense(env, lp, sense, i, i);
265 // // status = CPXgetrhs(env, lp, rhs, i, i);
267 // // switch (sense[0]) {
268 // // case 'L'://<= constraint
270 // // case 'E'://= constraint
272 // // case 'G'://>= constraint
274 // // case 'R'://ranged constraint
280 // // status = CPXchgcoef(env, lp, i, -2, value_rng);
283 void LpCplex::_getRowBounds(int i, Value &lb, Value &ub) const
286 CPXgetsense(env, lp, &sense,i,i);
292 CPXgetcoef(env, lp, i, -1, &ub);
295 CPXgetcoef(env, lp, i, -1, &lb);
298 CPXgetcoef(env, lp, i, -1, &lb);
302 CPXgetcoef(env, lp, i, -1, &lb);
304 CPXgetcoef(env, lp, i, -2, &x);
310 void LpCplex::_setObjCoeff(int i, Value obj_coef)
312 CPXchgcoef(env, lp, -1, i, obj_coef);
315 LpCplex::Value LpCplex::_getObjCoeff(int i) const
318 CPXgetcoef(env, lp, -1, i, &x);
322 void LpCplex::_clearObj()
324 for (int i=0;i< CPXgetnumcols(env, lp);++i){
325 CPXchgcoef(env, lp, -1, i, 0);
329 // The routine returns zero unless an error occurred during the
330 // optimization. Examples of errors include exhausting available
331 // memory (CPXERR_NO_MEMORY) or encountering invalid data in the
332 // CPLEX problem object (CPXERR_NO_PROBLEM). Exceeding a
333 // user-specified CPLEX limit, or proving the model infeasible or
334 // unbounded, are not considered errors. Note that a zero return
335 // value does not necessarily mean that a solution exists. Use query
336 // routines CPXsolninfo, CPXgetstat, and CPXsolution to obtain
337 // further information about the status of the optimization.
338 LpCplex::SolveExitStatus LpCplex::_solve()
341 status = CPXlpopt(env, lp);
342 //status = CPXprimopt(env, lp);
343 #if CPX_VERSION >= 800
350 switch (CPXgetstat(env, lp))
352 case CPX_STAT_OPTIMAL:
353 case CPX_STAT_INFEASIBLE:
354 case CPX_STAT_UNBOUNDED:
362 //We want to exclude some cases
363 switch (CPXgetstat(env, lp)){
365 case CPX_IT_LIM_FEAS:
366 case CPX_IT_LIM_INFEAS:
367 case CPX_TIME_LIM_FEAS:
368 case CPX_TIME_LIM_INFEAS:
380 LpCplex::Value LpCplex::_getPrimal(int i) const
383 CPXgetx(env, lp, &x, i, i);
387 LpCplex::Value LpCplex::_getDual(int i) const
390 CPXgetpi(env, lp, &y, i, i);
394 LpCplex::Value LpCplex::_getPrimalValue() const
397 //method = CPXgetmethod (env, lp);
398 //printf("CPXgetprobtype %d \n",CPXgetprobtype(env,lp));
399 status = CPXgetobjval(env, lp, &objval);
400 //printf("Objective value: %g \n",objval);
403 bool LpCplex::_isBasicCol(int i) const
405 int cstat[CPXgetnumcols(env, lp)];
406 CPXgetbase(env, lp, cstat, NULL);
407 return (cstat[i]==CPX_BASIC);
410 //7.5-os cplex statusai (Vigyazat: a 9.0-asei masok!)
411 // 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.
413 // For Simplex, Barrier
415 // Optimal solution found
417 // Problem infeasible
421 // Objective limit exceeded in Phase II
423 // Iteration limit exceeded in Phase II
424 // 6 CPX_IT_LIM_INFEAS
425 // Iteration limit exceeded in Phase I
426 // 7 CPX_TIME_LIM_FEAS
427 // Time limit exceeded in Phase II
428 // 8 CPX_TIME_LIM_INFEAS
429 // Time limit exceeded in Phase I
430 // 9 CPX_NUM_BEST_FEAS
431 // Problem non-optimal, singularities in Phase II
432 // 10 CPX_NUM_BEST_INFEAS
433 // Problem non-optimal, singularities in Phase I
434 // 11 CPX_OPTIMAL_INFEAS
435 // Optimal solution found, unscaled infeasibilities
437 // Aborted in Phase II
438 // 13 CPX_ABORT_INFEAS
439 // Aborted in Phase I
440 // 14 CPX_ABORT_DUAL_INFEAS
441 // Aborted in barrier, dual infeasible
442 // 15 CPX_ABORT_PRIM_INFEAS
443 // Aborted in barrier, primal infeasible
444 // 16 CPX_ABORT_PRIM_DUAL_INFEAS
445 // Aborted in barrier, primal and dual infeasible
446 // 17 CPX_ABORT_PRIM_DUAL_FEAS
447 // Aborted in barrier, primal and dual feasible
448 // 18 CPX_ABORT_CROSSOVER
449 // Aborted in crossover
451 // Infeasible or unbounded
455 // Ezeket hova tegyem:
456 // ??case CPX_ABORT_DUAL_INFEAS
457 // ??case CPX_ABORT_CROSSOVER
458 // ??case CPX_INForUNBD
461 //Some more interesting stuff:
463 // CPX_PARAM_LPMETHOD 1062 int LPMETHOD
468 // 4 Standard Barrier
470 // Description: Method for linear optimization.
471 // 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
472 void statusSwitch(CPXENVptr env,int& stat){
473 #if CPX_VERSION < 900
475 CPXgetintparam (env,CPX_PARAM_LPMETHOD,&lpmethod);
477 if (stat==CPX_UNBOUNDED){
481 if (stat==CPX_INFEASIBLE)
488 LpCplex::SolutionStatus LpCplex::_getPrimalStatus() const
490 //Unboundedness not treated well: the following is from cplex 9.0 doc
491 // About Unboundedness
493 // The treatment of models that are unbounded involves a few
494 // subtleties. Specifically, a declaration of unboundedness means that
495 // ILOG CPLEX has determined that the model has an unbounded
496 // ray. Given any feasible solution x with objective z, a multiple of
497 // the unbounded ray can be added to x to give a feasible solution
498 // with objective z-1 (or z+1 for maximization models). Thus, if a
499 // feasible solution exists, then the optimal objective is
500 // unbounded. Note that ILOG CPLEX has not necessarily concluded that
501 // a feasible solution exists. Users can call the routine CPXsolninfo
502 // to determine whether ILOG CPLEX has also concluded that the model
503 // has a feasible solution.
505 int stat = CPXgetstat(env, lp);
506 #if CPX_VERSION >= 800
509 case CPX_STAT_OPTIMAL:
511 case CPX_STAT_UNBOUNDED:
513 case CPX_STAT_INFEASIBLE:
519 statusSwitch(env,stat);
520 //CPXgetstat(env, lp);
521 //printf("A primal status: %d, CPX_OPTIMAL=%d \n",stat,CPX_OPTIMAL);
524 return UNDEFINED; //Undefined
525 case CPX_OPTIMAL://Optimal
527 case CPX_UNBOUNDED://Unbounded
528 return INFEASIBLE;//In case of dual simplex
530 case CPX_INFEASIBLE://Infeasible
531 // case CPX_IT_LIM_INFEAS:
532 // case CPX_TIME_LIM_INFEAS:
533 // case CPX_NUM_BEST_INFEAS:
534 // case CPX_OPTIMAL_INFEAS:
535 // case CPX_ABORT_INFEAS:
536 // case CPX_ABORT_PRIM_INFEAS:
537 // case CPX_ABORT_PRIM_DUAL_INFEAS:
538 return INFINITE;//In case of dual simplex
541 // case CPX_IT_LIM_FEAS:
542 // case CPX_TIME_LIM_FEAS:
543 // case CPX_NUM_BEST_FEAS:
544 // case CPX_ABORT_FEAS:
545 // case CPX_ABORT_PRIM_DUAL_FEAS:
548 return UNDEFINED; //Everything else comes here
554 //9.0-as cplex verzio statusai
555 // CPX_STAT_ABORT_DUAL_OBJ_LIM
556 // CPX_STAT_ABORT_IT_LIM
557 // CPX_STAT_ABORT_OBJ_LIM
558 // CPX_STAT_ABORT_PRIM_OBJ_LIM
559 // CPX_STAT_ABORT_TIME_LIM
560 // CPX_STAT_ABORT_USER
561 // CPX_STAT_FEASIBLE_RELAXED
562 // CPX_STAT_INFEASIBLE
563 // CPX_STAT_INForUNBD
566 // CPX_STAT_OPTIMAL_FACE_UNBOUNDED
567 // CPX_STAT_OPTIMAL_INFEAS
568 // CPX_STAT_OPTIMAL_RELAXED
569 // CPX_STAT_UNBOUNDED
571 LpCplex::SolutionStatus LpCplex::_getDualStatus() const
573 int stat = CPXgetstat(env, lp);
574 #if CPX_VERSION >= 800
577 case CPX_STAT_OPTIMAL:
579 case CPX_STAT_UNBOUNDED:
585 statusSwitch(env,stat);
588 return UNDEFINED; //Undefined
589 case CPX_OPTIMAL://Optimal
594 return UNDEFINED; //Everything else comes here
600 LpCplex::ProblemTypes LpCplex::_getProblemType() const
602 int stat = CPXgetstat(env, lp);
603 #if CPX_VERSION >= 800
606 case CPX_STAT_OPTIMAL:
607 return PRIMAL_DUAL_FEASIBLE;
608 case CPX_STAT_UNBOUNDED:
609 return PRIMAL_FEASIBLE_DUAL_INFEASIBLE;
615 case CPX_OPTIMAL://Optimal
616 return PRIMAL_DUAL_FEASIBLE;
618 return PRIMAL_FEASIBLE_DUAL_INFEASIBLE;
619 // return PRIMAL_INFEASIBLE_DUAL_FEASIBLE;
620 // return PRIMAL_DUAL_INFEASIBLE;
622 //Seems to be that this is all we can say for sure
631 void LpCplex::_setMax()
633 CPXchgobjsen(env, lp, CPX_MAX);
635 void LpCplex::_setMin()
637 CPXchgobjsen(env, lp, CPX_MIN);
640 bool LpCplex::_isMax() const
642 if (CPXgetobjsen(env, lp)==CPX_MAX)