1 /* -*- mode: C++; indent-tabs-mode: nil; -*-
3 * This file is a part of LEMON, a generic C++ optimization library.
5 * Copyright (C) 2003-2013
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
23 #include <lemon/cplex.h>
26 #include <ilcplex/cplex.h>
31 ///\brief Implementation of the LEMON-CPLEX lp solver interface.
34 CplexEnv::LicenseError::LicenseError(int status) {
35 if (!CPXgeterrorstring(0, status, _message)) {
36 std::strcpy(_message, "Cplex unknown error");
40 CplexEnv::CplexEnv() {
44 _env = CPXopenCPLEX(&status);
48 throw LicenseError(status);
52 CplexEnv::CplexEnv(const CplexEnv& other) {
58 CplexEnv& CplexEnv::operator=(const CplexEnv& other) {
65 CplexEnv::~CplexEnv() {
73 CplexBase::CplexBase() : LpBase() {
75 _prob = CPXcreateprob(cplexEnv(), &status, "Cplex problem");
76 messageLevel(MESSAGE_NOTHING);
79 CplexBase::CplexBase(const CplexEnv& env)
80 : LpBase(), _env(env) {
82 _prob = CPXcreateprob(cplexEnv(), &status, "Cplex problem");
83 messageLevel(MESSAGE_NOTHING);
86 CplexBase::CplexBase(const CplexBase& cplex)
89 _prob = CPXcloneprob(cplexEnv(), cplex._prob, &status);
92 messageLevel(MESSAGE_NOTHING);
95 CplexBase::~CplexBase() {
96 CPXfreeprob(cplexEnv(),&_prob);
99 int CplexBase::_addCol() {
100 int i = CPXgetnumcols(cplexEnv(), _prob);
101 double lb = -INF, ub = INF;
102 CPXnewcols(cplexEnv(), _prob, 1, 0, &lb, &ub, 0, 0);
107 int CplexBase::_addRow() {
108 int i = CPXgetnumrows(cplexEnv(), _prob);
109 const double ub = INF;
111 CPXnewrows(cplexEnv(), _prob, 1, &ub, &s, 0, 0);
115 int CplexBase::_addRow(Value lb, ExprIterator b,
116 ExprIterator e, Value ub) {
117 int i = CPXgetnumrows(cplexEnv(), _prob);
121 std::vector<int> indices;
122 std::vector<Value> values;
124 for(ExprIterator it=b; it!=e; ++it) {
125 indices.push_back(it->first);
126 values.push_back(it->second);
131 CPXaddrows(cplexEnv(), _prob, 0, 1, values.size(), &ub, &s,
132 &rmatbeg, &indices.front(), &values.front(), 0, 0);
133 } else if (ub == INF) {
135 CPXaddrows(cplexEnv(), _prob, 0, 1, values.size(), &lb, &s,
136 &rmatbeg, &indices.front(), &values.front(), 0, 0);
137 } else if (lb == ub){
139 CPXaddrows(cplexEnv(), _prob, 0, 1, values.size(), &lb, &s,
140 &rmatbeg, &indices.front(), &values.front(), 0, 0);
143 double len = ub - lb;
144 CPXaddrows(cplexEnv(), _prob, 0, 1, values.size(), &ub, &s,
145 &rmatbeg, &indices.front(), &values.front(), 0, 0);
146 CPXchgrngval(cplexEnv(), _prob, 1, &i, &len);
152 void CplexBase::_eraseCol(int i) {
153 CPXdelcols(cplexEnv(), _prob, i, i);
156 void CplexBase::_eraseRow(int i) {
157 CPXdelrows(cplexEnv(), _prob, i, i);
160 void CplexBase::_eraseColId(int i) {
162 _cols.shiftIndices(i);
164 void CplexBase::_eraseRowId(int i) {
166 _rows.shiftIndices(i);
169 void CplexBase::_getColName(int col, std::string &name) const {
171 CPXgetcolname(cplexEnv(), _prob, 0, 0, 0, &size, col, col);
178 std::vector<char> buf(size);
181 CPXgetcolname(cplexEnv(), _prob, &cname, &buf.front(), size,
186 void CplexBase::_setColName(int col, const std::string &name) {
188 cname = const_cast<char*>(name.c_str());
189 CPXchgcolname(cplexEnv(), _prob, 1, &col, &cname);
192 int CplexBase::_colByName(const std::string& name) const {
194 if (CPXgetcolindex(cplexEnv(), _prob,
195 const_cast<char*>(name.c_str()), &index) == 0) {
201 void CplexBase::_getRowName(int row, std::string &name) const {
203 CPXgetrowname(cplexEnv(), _prob, 0, 0, 0, &size, row, row);
210 std::vector<char> buf(size);
213 CPXgetrowname(cplexEnv(), _prob, &cname, &buf.front(), size,
218 void CplexBase::_setRowName(int row, const std::string &name) {
220 cname = const_cast<char*>(name.c_str());
221 CPXchgrowname(cplexEnv(), _prob, 1, &row, &cname);
224 int CplexBase::_rowByName(const std::string& name) const {
226 if (CPXgetrowindex(cplexEnv(), _prob,
227 const_cast<char*>(name.c_str()), &index) == 0) {
233 void CplexBase::_setRowCoeffs(int i, ExprIterator b,
236 std::vector<int> indices;
237 std::vector<int> rowlist;
238 std::vector<Value> values;
240 for(ExprIterator it=b; it!=e; ++it) {
241 indices.push_back(it->first);
242 values.push_back(it->second);
243 rowlist.push_back(i);
246 CPXchgcoeflist(cplexEnv(), _prob, values.size(),
247 &rowlist.front(), &indices.front(), &values.front());
250 void CplexBase::_getRowCoeffs(int i, InsertIterator b) const {
251 int tmp1, tmp2, tmp3, length;
252 CPXgetrows(cplexEnv(), _prob, &tmp1, &tmp2, 0, 0, 0, &length, i, i);
255 std::vector<int> indices(length);
256 std::vector<double> values(length);
258 CPXgetrows(cplexEnv(), _prob, &tmp1, &tmp2,
259 &indices.front(), &values.front(),
260 length, &tmp3, i, i);
262 for (int i = 0; i < length; ++i) {
263 *b = std::make_pair(indices[i], values[i]);
268 void CplexBase::_setColCoeffs(int i, ExprIterator b, ExprIterator e) {
269 std::vector<int> indices;
270 std::vector<int> collist;
271 std::vector<Value> values;
273 for(ExprIterator it=b; it!=e; ++it) {
274 indices.push_back(it->first);
275 values.push_back(it->second);
276 collist.push_back(i);
279 CPXchgcoeflist(cplexEnv(), _prob, values.size(),
280 &indices.front(), &collist.front(), &values.front());
283 void CplexBase::_getColCoeffs(int i, InsertIterator b) const {
285 int tmp1, tmp2, tmp3, length;
286 CPXgetcols(cplexEnv(), _prob, &tmp1, &tmp2, 0, 0, 0, &length, i, i);
289 std::vector<int> indices(length);
290 std::vector<double> values(length);
292 CPXgetcols(cplexEnv(), _prob, &tmp1, &tmp2,
293 &indices.front(), &values.front(),
294 length, &tmp3, i, i);
296 for (int i = 0; i < length; ++i) {
297 *b = std::make_pair(indices[i], values[i]);
303 void CplexBase::_setCoeff(int row, int col, Value value) {
304 CPXchgcoef(cplexEnv(), _prob, row, col, value);
307 CplexBase::Value CplexBase::_getCoeff(int row, int col) const {
308 CplexBase::Value value;
309 CPXgetcoef(cplexEnv(), _prob, row, col, &value);
313 void CplexBase::_setColLowerBound(int i, Value value) {
315 CPXchgbds(cplexEnv(), _prob, 1, &i, &s, &value);
318 CplexBase::Value CplexBase::_getColLowerBound(int i) const {
319 CplexBase::Value res;
320 CPXgetlb(cplexEnv(), _prob, &res, i, i);
321 return res <= -CPX_INFBOUND ? -INF : res;
324 void CplexBase::_setColUpperBound(int i, Value value)
327 CPXchgbds(cplexEnv(), _prob, 1, &i, &s, &value);
330 CplexBase::Value CplexBase::_getColUpperBound(int i) const {
331 CplexBase::Value res;
332 CPXgetub(cplexEnv(), _prob, &res, i, i);
333 return res >= CPX_INFBOUND ? INF : res;
336 CplexBase::Value CplexBase::_getRowLowerBound(int i) const {
338 CPXgetsense(cplexEnv(), _prob, &s, i, i);
339 CplexBase::Value res;
345 CPXgetrhs(cplexEnv(), _prob, &res, i, i);
346 return res <= -CPX_INFBOUND ? -INF : res;
352 CplexBase::Value CplexBase::_getRowUpperBound(int i) const {
354 CPXgetsense(cplexEnv(), _prob, &s, i, i);
355 CplexBase::Value res;
360 CPXgetrhs(cplexEnv(), _prob, &res, i, i);
361 return res >= CPX_INFBOUND ? INF : res;
363 CPXgetrhs(cplexEnv(), _prob, &res, i, i);
366 CPXgetrngval(cplexEnv(), _prob, &rng, i, i);
369 return res >= CPX_INFBOUND ? INF : res;
375 //This is easier to implement
376 void CplexBase::_set_row_bounds(int i, Value lb, Value ub) {
379 CPXchgsense(cplexEnv(), _prob, 1, &i, &s);
380 CPXchgrhs(cplexEnv(), _prob, 1, &i, &ub);
381 } else if (ub == INF) {
383 CPXchgsense(cplexEnv(), _prob, 1, &i, &s);
384 CPXchgrhs(cplexEnv(), _prob, 1, &i, &lb);
385 } else if (lb == ub){
387 CPXchgsense(cplexEnv(), _prob, 1, &i, &s);
388 CPXchgrhs(cplexEnv(), _prob, 1, &i, &lb);
391 CPXchgsense(cplexEnv(), _prob, 1, &i, &s);
392 CPXchgrhs(cplexEnv(), _prob, 1, &i, &lb);
393 double len = ub - lb;
394 CPXchgrngval(cplexEnv(), _prob, 1, &i, &len);
398 void CplexBase::_setRowLowerBound(int i, Value lb)
400 LEMON_ASSERT(lb != INF, "Invalid bound");
401 _set_row_bounds(i, lb, CplexBase::_getRowUpperBound(i));
404 void CplexBase::_setRowUpperBound(int i, Value ub)
407 LEMON_ASSERT(ub != -INF, "Invalid bound");
408 _set_row_bounds(i, CplexBase::_getRowLowerBound(i), ub);
411 void CplexBase::_setObjCoeffs(ExprIterator b, ExprIterator e)
413 std::vector<int> indices;
414 std::vector<Value> values;
415 for(ExprIterator it=b; it!=e; ++it) {
416 indices.push_back(it->first);
417 values.push_back(it->second);
419 CPXchgobj(cplexEnv(), _prob, values.size(),
420 &indices.front(), &values.front());
424 void CplexBase::_getObjCoeffs(InsertIterator b) const
426 int num = CPXgetnumcols(cplexEnv(), _prob);
427 std::vector<Value> x(num);
429 CPXgetobj(cplexEnv(), _prob, &x.front(), 0, num - 1);
430 for (int i = 0; i < num; ++i) {
432 *b = std::make_pair(i, x[i]);
438 void CplexBase::_setObjCoeff(int i, Value obj_coef)
440 CPXchgobj(cplexEnv(), _prob, 1, &i, &obj_coef);
443 CplexBase::Value CplexBase::_getObjCoeff(int i) const
446 CPXgetobj(cplexEnv(), _prob, &x, i, i);
450 void CplexBase::_setSense(CplexBase::Sense sense) {
453 CPXchgobjsen(cplexEnv(), _prob, CPX_MIN);
456 CPXchgobjsen(cplexEnv(), _prob, CPX_MAX);
461 CplexBase::Sense CplexBase::_getSense() const {
462 switch (CPXgetobjsen(cplexEnv(), _prob)) {
468 LEMON_ASSERT(false, "Invalid sense");
469 return CplexBase::Sense();
473 void CplexBase::_clear() {
474 CPXfreeprob(cplexEnv(),&_prob);
476 _prob = CPXcreateprob(cplexEnv(), &status, "Cplex problem");
479 void CplexBase::_messageLevel(MessageLevel level) {
481 case MESSAGE_NOTHING:
482 _message_enabled = false;
485 case MESSAGE_WARNING:
487 case MESSAGE_VERBOSE:
488 _message_enabled = true;
493 void CplexBase::_applyMessageLevel() {
494 CPXsetintparam(cplexEnv(), CPX_PARAM_SCRIND,
495 _message_enabled ? CPX_ON : CPX_OFF);
498 void CplexBase::_write(std::string file, std::string format) const
500 if(format == "MPS" || format == "LP")
501 CPXwriteprob(cplexEnv(), cplexLp(), file.c_str(), format.c_str());
502 else if(format == "SOL")
503 CPXsolwrite(cplexEnv(), cplexLp(), file.c_str());
504 else throw UnsupportedFormatError(format);
512 : LpBase(), LpSolver(), CplexBase() {}
514 CplexLp::CplexLp(const CplexEnv& env)
515 : LpBase(), LpSolver(), CplexBase(env) {}
517 CplexLp::CplexLp(const CplexLp& other)
518 : LpBase(), LpSolver(), CplexBase(other) {}
520 CplexLp::~CplexLp() {}
522 CplexLp* CplexLp::newSolver() const { return new CplexLp; }
523 CplexLp* CplexLp::cloneSolver() const {return new CplexLp(*this); }
525 const char* CplexLp::_solverName() const { return "CplexLp"; }
527 void CplexLp::_clear_temporals() {
534 // The routine returns zero unless an error occurred during the
535 // optimization. Examples of errors include exhausting available
536 // memory (CPXERR_NO_MEMORY) or encountering invalid data in the
537 // CPLEX problem object (CPXERR_NO_PROBLEM). Exceeding a
538 // user-specified CPLEX limit, or proving the model infeasible or
539 // unbounded, are not considered errors. Note that a zero return
540 // value does not necessarily mean that a solution exists. Use query
541 // routines CPXsolninfo, CPXgetstat, and CPXsolution to obtain
542 // further information about the status of the optimization.
543 CplexLp::SolveExitStatus CplexLp::convertStatus(int status) {
544 #if CPX_VERSION >= 800
546 switch (CPXgetstat(cplexEnv(), _prob)) {
547 case CPX_STAT_OPTIMAL:
548 case CPX_STAT_INFEASIBLE:
549 case CPX_STAT_UNBOUNDED:
559 //We want to exclude some cases
560 switch (CPXgetstat(cplexEnv(), _prob)) {
562 case CPX_IT_LIM_FEAS:
563 case CPX_IT_LIM_INFEAS:
564 case CPX_TIME_LIM_FEAS:
565 case CPX_TIME_LIM_INFEAS:
576 CplexLp::SolveExitStatus CplexLp::_solve() {
578 _applyMessageLevel();
579 return convertStatus(CPXlpopt(cplexEnv(), _prob));
582 CplexLp::SolveExitStatus CplexLp::solvePrimal() {
584 _applyMessageLevel();
585 return convertStatus(CPXprimopt(cplexEnv(), _prob));
588 CplexLp::SolveExitStatus CplexLp::solveDual() {
590 _applyMessageLevel();
591 return convertStatus(CPXdualopt(cplexEnv(), _prob));
594 CplexLp::SolveExitStatus CplexLp::solveBarrier() {
596 _applyMessageLevel();
597 return convertStatus(CPXbaropt(cplexEnv(), _prob));
600 CplexLp::Value CplexLp::_getPrimal(int i) const {
602 CPXgetx(cplexEnv(), _prob, &x, i, i);
606 CplexLp::Value CplexLp::_getDual(int i) const {
608 CPXgetpi(cplexEnv(), _prob, &y, i, i);
612 CplexLp::Value CplexLp::_getPrimalValue() const {
614 CPXgetobjval(cplexEnv(), _prob, &objval);
618 CplexLp::VarStatus CplexLp::_getColStatus(int i) const {
619 if (_col_status.empty()) {
620 _col_status.resize(CPXgetnumcols(cplexEnv(), _prob));
621 CPXgetbase(cplexEnv(), _prob, &_col_status.front(), 0);
623 switch (_col_status[i]) {
633 LEMON_ASSERT(false, "Wrong column status");
634 return CplexLp::VarStatus();
638 CplexLp::VarStatus CplexLp::_getRowStatus(int i) const {
639 if (_row_status.empty()) {
640 _row_status.resize(CPXgetnumrows(cplexEnv(), _prob));
641 CPXgetbase(cplexEnv(), _prob, 0, &_row_status.front());
643 switch (_row_status[i]) {
649 CPXgetsense(cplexEnv(), _prob, &s, i, i);
650 return s != 'L' ? LOWER : UPPER;
655 LEMON_ASSERT(false, "Wrong row status");
656 return CplexLp::VarStatus();
660 CplexLp::Value CplexLp::_getPrimalRay(int i) const {
661 if (_primal_ray.empty()) {
662 _primal_ray.resize(CPXgetnumcols(cplexEnv(), _prob));
663 CPXgetray(cplexEnv(), _prob, &_primal_ray.front());
665 return _primal_ray[i];
668 CplexLp::Value CplexLp::_getDualRay(int i) const {
669 if (_dual_ray.empty()) {
675 // Cplex 7.0 status values
676 // This table lists the statuses, returned by the CPXgetstat()
677 // routine, for solutions to LP problems or mixed integer problems. If
678 // no solution exists, the return value is zero.
680 // For Simplex, Barrier
682 // Optimal solution found
684 // Problem infeasible
688 // Objective limit exceeded in Phase II
690 // Iteration limit exceeded in Phase II
691 // 6 CPX_IT_LIM_INFEAS
692 // Iteration limit exceeded in Phase I
693 // 7 CPX_TIME_LIM_FEAS
694 // Time limit exceeded in Phase II
695 // 8 CPX_TIME_LIM_INFEAS
696 // Time limit exceeded in Phase I
697 // 9 CPX_NUM_BEST_FEAS
698 // Problem non-optimal, singularities in Phase II
699 // 10 CPX_NUM_BEST_INFEAS
700 // Problem non-optimal, singularities in Phase I
701 // 11 CPX_OPTIMAL_INFEAS
702 // Optimal solution found, unscaled infeasibilities
704 // Aborted in Phase II
705 // 13 CPX_ABORT_INFEAS
706 // Aborted in Phase I
707 // 14 CPX_ABORT_DUAL_INFEAS
708 // Aborted in barrier, dual infeasible
709 // 15 CPX_ABORT_PRIM_INFEAS
710 // Aborted in barrier, primal infeasible
711 // 16 CPX_ABORT_PRIM_DUAL_INFEAS
712 // Aborted in barrier, primal and dual infeasible
713 // 17 CPX_ABORT_PRIM_DUAL_FEAS
714 // Aborted in barrier, primal and dual feasible
715 // 18 CPX_ABORT_CROSSOVER
716 // Aborted in crossover
718 // Infeasible or unbounded
722 // Pending return values
723 // ??case CPX_ABORT_DUAL_INFEAS
724 // ??case CPX_ABORT_CROSSOVER
725 // ??case CPX_INForUNBD
728 //Some more interesting stuff:
730 // CPX_PARAM_PROBMETHOD 1062 int LPMETHOD
735 // 4 Standard Barrier
737 // Description: Method for linear optimization.
738 // Determines which algorithm is used when CPXlpopt() (or "optimize"
739 // in the Interactive Optimizer) is called. Currently the behavior of
740 // the "Automatic" setting is that CPLEX simply invokes the dual
741 // simplex method, but this capability may be expanded in the future
742 // so that CPLEX chooses the method based on problem characteristics
743 #if CPX_VERSION < 900
744 void statusSwitch(CPXENVptr cplexEnv(),int& stat){
746 CPXgetintparam (cplexEnv(),CPX_PARAM_PROBMETHOD,&lpmethod);
748 if (stat==CPX_UNBOUNDED){
752 if (stat==CPX_INFEASIBLE)
758 void statusSwitch(CPXENVptr,int&){}
761 CplexLp::ProblemType CplexLp::_getPrimalType() const {
762 // Unboundedness not treated well: the following is from cplex 9.0 doc
763 // About Unboundedness
765 // The treatment of models that are unbounded involves a few
766 // subtleties. Specifically, a declaration of unboundedness means that
767 // ILOG CPLEX has determined that the model has an unbounded
768 // ray. Given any feasible solution x with objective z, a multiple of
769 // the unbounded ray can be added to x to give a feasible solution
770 // with objective z-1 (or z+1 for maximization models). Thus, if a
771 // feasible solution exists, then the optimal objective is
772 // unbounded. Note that ILOG CPLEX has not necessarily concluded that
773 // a feasible solution exists. Users can call the routine CPXsolninfo
774 // to determine whether ILOG CPLEX has also concluded that the model
775 // has a feasible solution.
777 int stat = CPXgetstat(cplexEnv(), _prob);
778 #if CPX_VERSION >= 800
781 case CPX_STAT_OPTIMAL:
783 case CPX_STAT_UNBOUNDED:
785 case CPX_STAT_INFEASIBLE:
791 statusSwitch(cplexEnv(),stat);
792 //CPXgetstat(cplexEnv(), _prob);
795 return UNDEFINED; //Undefined
796 case CPX_OPTIMAL://Optimal
798 case CPX_UNBOUNDED://Unbounded
799 return INFEASIBLE;//In case of dual simplex
801 case CPX_INFEASIBLE://Infeasible
802 // case CPX_IT_LIM_INFEAS:
803 // case CPX_TIME_LIM_INFEAS:
804 // case CPX_NUM_BEST_INFEAS:
805 // case CPX_OPTIMAL_INFEAS:
806 // case CPX_ABORT_INFEAS:
807 // case CPX_ABORT_PRIM_INFEAS:
808 // case CPX_ABORT_PRIM_DUAL_INFEAS:
809 return UNBOUNDED;//In case of dual simplex
812 // case CPX_IT_LIM_FEAS:
813 // case CPX_TIME_LIM_FEAS:
814 // case CPX_NUM_BEST_FEAS:
815 // case CPX_ABORT_FEAS:
816 // case CPX_ABORT_PRIM_DUAL_FEAS:
819 return UNDEFINED; //Everything else comes here
825 // Cplex 9.0 status values
826 // CPX_STAT_ABORT_DUAL_OBJ_LIM
827 // CPX_STAT_ABORT_IT_LIM
828 // CPX_STAT_ABORT_OBJ_LIM
829 // CPX_STAT_ABORT_PRIM_OBJ_LIM
830 // CPX_STAT_ABORT_TIME_LIM
831 // CPX_STAT_ABORT_USER
832 // CPX_STAT_FEASIBLE_RELAXED
833 // CPX_STAT_INFEASIBLE
834 // CPX_STAT_INForUNBD
837 // CPX_STAT_OPTIMAL_FACE_UNBOUNDED
838 // CPX_STAT_OPTIMAL_INFEAS
839 // CPX_STAT_OPTIMAL_RELAXED
840 // CPX_STAT_UNBOUNDED
842 CplexLp::ProblemType CplexLp::_getDualType() const {
843 int stat = CPXgetstat(cplexEnv(), _prob);
844 #if CPX_VERSION >= 800
846 case CPX_STAT_OPTIMAL:
848 case CPX_STAT_UNBOUNDED:
854 statusSwitch(cplexEnv(),stat);
857 return UNDEFINED; //Undefined
858 case CPX_OPTIMAL://Optimal
863 return UNDEFINED; //Everything else comes here
872 : LpBase(), MipSolver(), CplexBase() {
874 #if CPX_VERSION < 800
875 CPXchgprobtype(cplexEnv(), _prob, CPXPROB_MIP);
877 CPXchgprobtype(cplexEnv(), _prob, CPXPROB_MILP);
881 CplexMip::CplexMip(const CplexEnv& env)
882 : LpBase(), MipSolver(), CplexBase(env) {
884 #if CPX_VERSION < 800
885 CPXchgprobtype(cplexEnv(), _prob, CPXPROB_MIP);
887 CPXchgprobtype(cplexEnv(), _prob, CPXPROB_MILP);
892 CplexMip::CplexMip(const CplexMip& other)
893 : LpBase(), MipSolver(), CplexBase(other) {}
895 CplexMip::~CplexMip() {}
897 CplexMip* CplexMip::newSolver() const { return new CplexMip; }
898 CplexMip* CplexMip::cloneSolver() const {return new CplexMip(*this); }
900 const char* CplexMip::_solverName() const { return "CplexMip"; }
902 void CplexMip::_setColType(int i, CplexMip::ColTypes col_type) {
904 // Note If a variable is to be changed to binary, a call to CPXchgbds
905 // should also be made to change the bounds to 0 and 1.
910 CPXchgctype (cplexEnv(), _prob, 1, &i, &t);
914 CPXchgctype (cplexEnv(), _prob, 1, &i, &t);
921 CplexMip::ColTypes CplexMip::_getColType(int i) const {
923 CPXgetctype (cplexEnv(), _prob, &t, i, i);
930 LEMON_ASSERT(false, "Invalid column type");
936 CplexMip::SolveExitStatus CplexMip::_solve() {
938 _applyMessageLevel();
939 status = CPXmipopt (cplexEnv(), _prob);
948 CplexMip::ProblemType CplexMip::_getType() const {
950 int stat = CPXgetstat(cplexEnv(), _prob);
952 //Fortunately, MIP statuses did not change for cplex 8.0
955 // Optimal integer solution has been found.
956 case CPXMIP_OPTIMAL_TOL:
957 // Optimal soluton with the tolerance defined by epgap or epagap has
960 //This also exists in later issues
961 // case CPXMIP_UNBOUNDED:
963 case CPXMIP_INFEASIBLE:
968 //Unboundedness not treated well: the following is from cplex 9.0 doc
969 // About Unboundedness
971 // The treatment of models that are unbounded involves a few
972 // subtleties. Specifically, a declaration of unboundedness means that
973 // ILOG CPLEX has determined that the model has an unbounded
974 // ray. Given any feasible solution x with objective z, a multiple of
975 // the unbounded ray can be added to x to give a feasible solution
976 // with objective z-1 (or z+1 for maximization models). Thus, if a
977 // feasible solution exists, then the optimal objective is
978 // unbounded. Note that ILOG CPLEX has not necessarily concluded that
979 // a feasible solution exists. Users can call the routine CPXsolninfo
980 // to determine whether ILOG CPLEX has also concluded that the model
981 // has a feasible solution.
984 CplexMip::Value CplexMip::_getSol(int i) const {
986 CPXgetmipx(cplexEnv(), _prob, &x, i, i);
990 CplexMip::Value CplexMip::_getSolValue() const {
992 CPXgetmipobjval(cplexEnv(), _prob, &objval);