/* -*- mode: C++; indent-tabs-mode: nil; -*-
* This file is a part of LEMON, a generic C++ optimization library.
* Copyright (C) 2003-2008
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
#include <lemon/lp_cplex.h>
#include <ilcplex/cplex.h>
///\brief Implementation of the LEMON-CPLEX lp solver interface.
// env = CPXopenCPLEXdevelop(&status);
env = CPXopenCPLEX(&status);
lp = CPXcreateprob(env, &status, "LP problem");
LpCplex::LpCplex(const LpCplex& cplex) : LpSolverBase() {
env = CPXopenCPLEX(&status);
lp = CPXcloneprob(env, cplex.lp, &status);
LpSolverBase* LpCplex::_newLp()
//The first approach opens a new environment
LpSolverBase* LpCplex::_copyLp() {
return new LpCplex(*this);
int i = CPXgetnumcols(env, lp);
status = CPXnewcols(env, lp, 1, NULL, lb, ub, NULL, NULL);
//We want a row that is not constrained
sense[0]='L';//<= constraint
int i = CPXgetnumrows(env, lp);
status = CPXnewrows(env, lp, 1, rhs, sense, NULL, NULL);
void LpCplex::_eraseCol(int i) {
CPXdelcols(env, lp, i, i);
void LpCplex::_eraseRow(int i) {
CPXdelrows(env, lp, i, i);
void LpCplex::_getColName(int col, std::string &name) const
CPXgetcolname(env, lp, 0, 0, 0, &storespace, col, col);
std::vector<char> buf(storespace);
///\bug return code unchecked for error
CPXgetcolname(env, lp, names, &*buf.begin(), storespace,
void LpCplex::_setColName(int col, const std::string &name)
names[0] = const_cast<char*>(name.c_str());
///\bug return code unchecked for error
CPXchgcolname(env, lp, 1, &col, names);
int LpCplex::_colByName(const std::string& name) const
if (CPXgetcolindex(env, lp,
const_cast<char*>(name.c_str()), &index) == 0) {
///\warning Data at index 0 is ignored in the arrays.
void LpCplex::_setRowCoeffs(int i, ConstRowIterator b, ConstRowIterator e)
std::vector<int> indices;
std::vector<int> rowlist;
std::vector<Value> values;
for(ConstRowIterator it=b; it!=e; ++it) {
indices.push_back(it->first);
values.push_back(it->second);
status = CPXchgcoeflist(env, lp, values.size(),
&rowlist[0], &indices[0], &values[0]);
void LpCplex::_getRowCoeffs(int i, RowIterator b) const {
int tmp1, tmp2, tmp3, length;
CPXgetrows(env, lp, &tmp1, &tmp2, 0, 0, 0, &length, i, i);
std::vector<int> indices(length);
std::vector<double> values(length);
CPXgetrows(env, lp, &tmp1, &tmp2, &indices[0], &values[0],
for (int i = 0; i < length; ++i) {
*b = std::make_pair(indices[i], values[i]);
void LpCplex::_setColCoeffs(int i, ConstColIterator b, ConstColIterator e)
std::vector<int> indices;
std::vector<int> collist;
std::vector<Value> values;
for(ConstColIterator it=b; it!=e; ++it) {
indices.push_back(it->first);
values.push_back(it->second);
status = CPXchgcoeflist(env, lp, values.size(),
&indices[0], &collist[0], &values[0]);
void LpCplex::_getColCoeffs(int i, ColIterator b) const {
int tmp1, tmp2, tmp3, length;
CPXgetcols(env, lp, &tmp1, &tmp2, 0, 0, 0, &length, i, i);
std::vector<int> indices(length);
std::vector<double> values(length);
CPXgetcols(env, lp, &tmp1, &tmp2, &indices[0], &values[0],
for (int i = 0; i < length; ++i) {
*b = std::make_pair(indices[i], values[i]);
void LpCplex::_setCoeff(int row, int col, Value value)
CPXchgcoef(env, lp, row, col, value);
LpCplex::Value LpCplex::_getCoeff(int row, int col) const
CPXgetcoef(env, lp, row, col, &value);
void LpCplex::_setColLowerBound(int i, Value value)
status = CPXchgbds(env, lp, 1, indices, lu, bd);
LpCplex::Value LpCplex::_getColLowerBound(int i) const
CPXgetlb (env, lp, &x, i, i);
if (x <= -CPX_INFBOUND) x = -INF;
void LpCplex::_setColUpperBound(int i, Value value)
status = CPXchgbds(env, lp, 1, indices, lu, bd);
LpCplex::Value LpCplex::_getColUpperBound(int i) const
CPXgetub (env, lp, &x, i, i);
if (x >= CPX_INFBOUND) x = INF;
//This will be easier to implement
void LpCplex::_setRowBounds(int i, Value lb, Value ub)
if (lb==INF || ub==-INF) {
CPXchgsense(env, lp, cnt, indices, sense);
CPXchgcoef(env, lp, i, -1, ub);
CPXchgsense(env, lp, cnt, indices, sense);
CPXchgcoef(env, lp, i, -1, lb);
CPXchgsense(env, lp, cnt, indices, sense);
CPXchgcoef(env, lp, i, -1, lb);
CPXchgsense(env, lp, cnt, indices, sense);
CPXchgcoef(env, lp, i, -1, lb);
CPXchgcoef(env, lp, i, -2, ub-lb);
// void LpCplex::_setRowLowerBound(int i, Value value)
// //Not implemented, obsolete
// void LpCplex::_setRowUpperBound(int i, Value value)
// //Not implemented, obsolete
// // //TODO Ezt kell meg megirni
// // //type of the problem
// // status = CPXgetsense(env, lp, sense, i, i);
// // status = CPXgetrhs(env, lp, rhs, i, i);
// // switch (sense[0]) {
// // case 'L'://<= constraint
// // case 'E'://= constraint
// // case 'G'://>= constraint
// // case 'R'://ranged constraint
// // status = CPXchgcoef(env, lp, i, -2, value_rng);
void LpCplex::_getRowBounds(int i, Value &lb, Value &ub) const
CPXgetsense(env, lp, &sense,i,i);
CPXgetcoef(env, lp, i, -1, &ub);
CPXgetcoef(env, lp, i, -1, &lb);
CPXgetcoef(env, lp, i, -1, &lb);
CPXgetcoef(env, lp, i, -1, &lb);
CPXgetcoef(env, lp, i, -2, &x);
void LpCplex::_setObjCoeff(int i, Value obj_coef)
CPXchgcoef(env, lp, -1, i, obj_coef);
LpCplex::Value LpCplex::_getObjCoeff(int i) const
CPXgetcoef(env, lp, -1, i, &x);
void LpCplex::_clearObj()
for (int i=0;i< CPXgetnumcols(env, lp);++i){
CPXchgcoef(env, lp, -1, i, 0);
// The routine returns zero unless an error occurred during the
// optimization. Examples of errors include exhausting available
// memory (CPXERR_NO_MEMORY) or encountering invalid data in the
// CPLEX problem object (CPXERR_NO_PROBLEM). Exceeding a
// user-specified CPLEX limit, or proving the model infeasible or
// unbounded, are not considered errors. Note that a zero return
// value does not necessarily mean that a solution exists. Use query
// routines CPXsolninfo, CPXgetstat, and CPXsolution to obtain
// further information about the status of the optimization.
LpCplex::SolveExitStatus LpCplex::_solve()
status = CPXlpopt(env, lp);
//status = CPXprimopt(env, lp);
switch (CPXgetstat(env, lp))
case CPX_STAT_INFEASIBLE:
//We want to exclude some cases
switch (CPXgetstat(env, lp)){
case CPX_TIME_LIM_INFEAS:
LpCplex::Value LpCplex::_getPrimal(int i) const
CPXgetx(env, lp, &x, i, i);
LpCplex::Value LpCplex::_getDual(int i) const
CPXgetpi(env, lp, &y, i, i);
LpCplex::Value LpCplex::_getPrimalValue() const
//method = CPXgetmethod (env, lp);
//printf("CPXgetprobtype %d \n",CPXgetprobtype(env,lp));
CPXgetobjval(env, lp, &objval);
//printf("Objective value: %g \n",objval);
bool LpCplex::_isBasicCol(int i) const
std::vector<int> cstat(CPXgetnumcols(env, lp));
CPXgetbase(env, lp, &*cstat.begin(), NULL);
return (cstat[i]==CPX_BASIC);
//7.5-os cplex statusai (Vigyazat: a 9.0-asei masok!)
// 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.
// Optimal solution found
// Objective limit exceeded in Phase II
// Iteration limit exceeded in Phase II
// Iteration limit exceeded in Phase I
// Time limit exceeded in Phase II
// Time limit exceeded in Phase I
// Problem non-optimal, singularities in Phase II
// 10 CPX_NUM_BEST_INFEAS
// Problem non-optimal, singularities in Phase I
// Optimal solution found, unscaled infeasibilities
// 14 CPX_ABORT_DUAL_INFEAS
// Aborted in barrier, dual infeasible
// 15 CPX_ABORT_PRIM_INFEAS
// Aborted in barrier, primal infeasible
// 16 CPX_ABORT_PRIM_DUAL_INFEAS
// Aborted in barrier, primal and dual infeasible
// 17 CPX_ABORT_PRIM_DUAL_FEAS
// Aborted in barrier, primal and dual feasible
// 18 CPX_ABORT_CROSSOVER
// Infeasible or unbounded
// ??case CPX_ABORT_DUAL_INFEAS
// ??case CPX_ABORT_CROSSOVER
//Some more interesting stuff:
// CPX_PARAM_LPMETHOD 1062 int LPMETHOD
// Description: Method for linear optimization.
// 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
void statusSwitch(CPXENVptr env,int& stat){
CPXgetintparam (env,CPX_PARAM_LPMETHOD,&lpmethod);
if (stat==CPX_UNBOUNDED){
if (stat==CPX_INFEASIBLE)
void statusSwitch(CPXENVptr,int&){}
LpCplex::SolutionStatus LpCplex::_getPrimalStatus() const
//Unboundedness not treated well: the following is from cplex 9.0 doc
// The treatment of models that are unbounded involves a few
// subtleties. Specifically, a declaration of unboundedness means that
// ILOG CPLEX has determined that the model has an unbounded
// ray. Given any feasible solution x with objective z, a multiple of
// the unbounded ray can be added to x to give a feasible solution
// with objective z-1 (or z+1 for maximization models). Thus, if a
// feasible solution exists, then the optimal objective is
// unbounded. Note that ILOG CPLEX has not necessarily concluded that
// a feasible solution exists. Users can call the routine CPXsolninfo
// to determine whether ILOG CPLEX has also concluded that the model
// has a feasible solution.
int stat = CPXgetstat(env, lp);
case CPX_STAT_INFEASIBLE:
//printf("A primal status: %d, CPX_OPTIMAL=%d \n",stat,CPX_OPTIMAL);
return UNDEFINED; //Undefined
case CPX_OPTIMAL:
//Optimal
case CPX_UNBOUNDED:
//Unbounded
return INFEASIBLE;//In case of dual simplex
case CPX_INFEASIBLE:
//Infeasible
// case CPX_IT_LIM_INFEAS:
// case CPX_TIME_LIM_INFEAS:
// case CPX_NUM_BEST_INFEAS:
// case CPX_OPTIMAL_INFEAS:
// case CPX_ABORT_INFEAS:
// case CPX_ABORT_PRIM_INFEAS:
// case CPX_ABORT_PRIM_DUAL_INFEAS:
return INFINITE;//In case of dual simplex
// case CPX_TIME_LIM_FEAS:
// case CPX_NUM_BEST_FEAS:
// case CPX_ABORT_PRIM_DUAL_FEAS:
return UNDEFINED; //Everything else comes here
//9.0-as cplex verzio statusai
// CPX_STAT_ABORT_DUAL_OBJ_LIM
// CPX_STAT_ABORT_OBJ_LIM
// CPX_STAT_ABORT_PRIM_OBJ_LIM
// CPX_STAT_ABORT_TIME_LIM
// CPX_STAT_FEASIBLE_RELAXED
// CPX_STAT_OPTIMAL_FACE_UNBOUNDED
// CPX_STAT_OPTIMAL_INFEAS
// CPX_STAT_OPTIMAL_RELAXED
LpCplex::SolutionStatus LpCplex::_getDualStatus() const
int stat = CPXgetstat(env, lp);
return UNDEFINED; //Undefined
case CPX_OPTIMAL:
//Optimal
return UNDEFINED; //Everything else comes here
LpCplex::ProblemTypes LpCplex::_getProblemType() const
int stat = CPXgetstat(env, lp);
return PRIMAL_DUAL_FEASIBLE;
return PRIMAL_FEASIBLE_DUAL_INFEASIBLE;
case CPX_OPTIMAL:
//Optimal
return PRIMAL_DUAL_FEASIBLE;
return PRIMAL_FEASIBLE_DUAL_INFEASIBLE;
// return PRIMAL_INFEASIBLE_DUAL_FEASIBLE;
// return PRIMAL_DUAL_INFEASIBLE;
//Seems to be that this is all we can say for sure
CPXchgobjsen(env, lp, CPX_MAX);
CPXchgobjsen(env, lp, CPX_MIN);
bool LpCplex::_isMax() const
if (CPXgetobjsen(env, lp)==CPX_MAX)