21#include "absl/strings/str_format.h" 
   22#include "absl/strings/str_split.h" 
   28#include "ilcplex/cplexx.h" 
   38#define CPX_NAN std::numeric_limits<double>::quiet_NaN() 
   44#define CHECK_STATUS(s)    \ 
   46    int const status_ = s; \ 
   47    CHECK_EQ(0, status_);  \ 
 
   86                              double new_value, 
double old_value);
 
  102  virtual int64_t 
nodes() 
const;
 
  115  virtual bool IsLP()
 const { 
return !mMip; }
 
  116  virtual bool IsMIP()
 const { 
return mMip; }
 
  119      const std::string& parameters) 
override;
 
  130      LOG(DFATAL) << 
"ComputeExactConditionNumber not implemented for" 
  131                  << 
" CPLEX_MIXED_INTEGER_PROGRAMMING";
 
  137      CHECK_STATUS(CPXXgetdblquality(mEnv, mLp, &kappa, CPX_EXACT_KAPPA));
 
  140    LOG(DFATAL) << 
"Cannot get exact condition number without solution";
 
 
  162  void InvalidateModelSynchronization() {
 
  186  bool const supportIncrementalExtraction;
 
  194    SlowSetCoefficient = 0x0001,
 
  195    SlowClearConstraint = 0x0002,
 
  196    SlowSetObjectiveCoefficient = 0x0004,
 
  197    SlowClearObjective = 0x0008,
 
  198    SlowSetConstraintBounds = 0x0010,
 
  199    SlowSetVariableInteger = 0x0020,
 
  200    SlowSetVariableBounds = 0x0040,
 
  201    SlowUpdatesAll = 0xffff
 
  207  unique_ptr<int[]> 
mutable mCstat;
 
  208  unique_ptr<int[]> 
mutable mRstat;
 
  211  static void MakeRhs(
double lb, 
double ub, 
double& rhs, 
char& sense,
 
 
  221      slowUpdates(static_cast<SlowUpdates>(SlowSetObjectiveCoefficient |
 
  222                                           SlowClearObjective)),
 
  223      supportIncrementalExtraction(false),
 
  228  mEnv = CPXXopenCPLEX(&status);
 
  230  DCHECK(mEnv != 
nullptr);  
 
  232  char const* name = 
solver_->name_.c_str();
 
  233  mLp = CPXXcreateprob(mEnv, &status, name);
 
  235  DCHECK(mLp != 
nullptr);  
 
  238  if (mMip) 
CHECK_STATUS(CPXXchgprobtype(mEnv, mLp, CPXPROB_MILP));
 
 
  252  int const major = version / 1000000;
 
  253  version -= major * 1000000;
 
  254  int const release = version / 10000;
 
  255  version -= release * 10000;
 
  256  int const mod = version / 100;
 
  257  version -= mod * 100;
 
  258  int const fix = version;
 
  260  return absl::StrFormat(
"CPLEX library version %d.%02d.%02d.%02d", major,
 
 
  272  const char* 
const name = 
solver_->name_.c_str();
 
  273  mLp = CPXXcreateprob(mEnv, &status, name);
 
  275  DCHECK(mLp != 
nullptr);  
 
  278  if (mMip) 
CHECK_STATUS(CPXXchgprobtype(mEnv, mLp, CPXPROB_MILP));
 
 
  287  CPXXchgobjsen(mEnv, mLp, maximize ? CPX_MAX : CPX_MIN);
 
 
  299  if (!supportIncrementalExtraction && !(slowUpdates & SlowSetVariableBounds)) {
 
  300    InvalidateModelSynchronization();
 
  306      char const lu[2] = {
'L', 
'U'};
 
  307      double const bd[2] = {lb, ub};
 
  308      CPXDIM 
const idx[2] = {var_index, var_index};
 
  313      InvalidateModelSynchronization();
 
 
  332  if (!supportIncrementalExtraction &&
 
  333      !(slowUpdates && SlowSetVariableInteger)) {
 
  334    InvalidateModelSynchronization();
 
  341        DCHECK_LE(var_index, CPXXgetnumcols(mEnv, mLp));
 
  342        char const type = integer ? CPX_INTEGER : CPX_CONTINUOUS;
 
  343        CHECK_STATUS(CPXXchgctype(mEnv, mLp, 1, &var_index, &type));
 
  345        InvalidateModelSynchronization();
 
  348          << 
"Attempt to change variable to integer in non-MIP problem!";
 
 
  354void CplexInterface::MakeRhs(
double lb, 
double ub, 
double& rhs, 
char& sense,
 
  361  } 
else if (lb > -CPX_INFBOUND && ub < CPX_INFBOUND) {
 
  381  } 
else if (ub < CPX_INFBOUND ||
 
  382             (std::abs(ub) == CPX_INFBOUND && std::abs(lb) > CPX_INFBOUND)) {
 
  387  } 
else if (lb > -CPX_INFBOUND ||
 
  388             (std::abs(lb) == CPX_INFBOUND && std::abs(ub) > CPX_INFBOUND)) {
 
  402    DCHECK_GT(std::abs(lb), CPX_INFBOUND);
 
  403    DCHECK_GT(std::abs(ub), CPX_INFBOUND);
 
  404    if (std::abs(lb) > std::abs(ub)) {
 
  405      rhs = (lb < 0) ? -CPX_INFBOUND : CPX_INFBOUND;
 
  408      rhs = (ub < 0) ? -CPX_INFBOUND : CPX_INFBOUND;
 
  424  if (!supportIncrementalExtraction &&
 
  425      !(slowUpdates & SlowSetConstraintBounds)) {
 
  426    InvalidateModelSynchronization();
 
  434      MakeRhs(lb, ub, rhs, sense, range);
 
  436      CHECK_STATUS(CPXXchgsense(mEnv, mLp, 1, &index, &sense));
 
  437      CHECK_STATUS(CPXXchgrngval(mEnv, mLp, 1, &index, &range));
 
  441      InvalidateModelSynchronization();
 
 
  453  InvalidateModelSynchronization();
 
 
  463  InvalidateModelSynchronization();
 
 
  468                                    double new_value, 
double) {
 
  478  if (!supportIncrementalExtraction && !(slowUpdates & SlowSetCoefficient)) {
 
  479    InvalidateModelSynchronization();
 
  481    int const row = constraint->
index();
 
  482    int const col = variable->
index();
 
  488      CHECK_STATUS(CPXXchgcoef(mEnv, mLp, row, col, new_value));
 
  492      InvalidateModelSynchronization();
 
 
  498  CPXDIM 
const row = constraint->
index();
 
  511  if (!(slowUpdates & SlowClearConstraint)) {
 
  512    InvalidateModelSynchronization();
 
  516    CPXDIM 
const len = constraint->coefficients_.size();
 
  517    unique_ptr<CPXDIM[]> rowind(
new CPXDIM[len]);
 
  518    unique_ptr<CPXDIM[]> colind(
new CPXDIM[len]);
 
  519    unique_ptr<double[]> val(
new double[len]);
 
  521    const auto& coeffs = constraint->coefficients_;
 
  522    for (
auto it(coeffs.begin()); it != coeffs.end(); ++it) {
 
  523      CPXDIM 
const col = it->first->index();
 
  533          CPXXchgcoeflist(mEnv, mLp, j, rowind.get(), colind.get(), val.get()));
 
 
  538                                             double coefficient) {
 
  539  CPXDIM 
const col = variable->
index();
 
  552  if (supportIncrementalExtraction ||
 
  553      (slowUpdates & SlowSetObjectiveCoefficient)) {
 
  554    CHECK_STATUS(CPXXchgobj(mEnv, mLp, 1, &col, &coefficient));
 
  556    InvalidateModelSynchronization();
 
 
  573  if (supportIncrementalExtraction || (slowUpdates & SlowClearObjective)) {
 
  574    CPXDIM 
const cols = CPXXgetnumcols(mEnv, mLp);
 
  575    unique_ptr<CPXDIM[]> ind(
new CPXDIM[cols]);
 
  576    unique_ptr<double[]> zero(
new double[cols]);
 
  578    const auto& coeffs = 
solver_->objective_->coefficients_;
 
  579    for (
auto it(coeffs.begin()); it != coeffs.end(); ++it) {
 
  580      CPXDIM 
const idx = it->first->index();
 
  583        DCHECK_LT(idx, cols);
 
  589    if (j > 0) 
CHECK_STATUS(CPXXchgobj(mEnv, mLp, j, ind.get(), zero.get()));
 
  592    InvalidateModelSynchronization();
 
 
  601    return static_cast<int64_t
>(CPXXgetmipitcnt(mEnv, mLp));
 
  603    return static_cast<int64_t
>(CPXXgetitcnt(mEnv, mLp));
 
 
  609    return static_cast<int64_t
>(CPXXgetnodecnt(mEnv, mLp));
 
  611    LOG(DFATAL) << 
"Number of nodes only available for discrete problems";
 
 
  618  switch (cplex_basis_status) {
 
  628      LOG(DFATAL) << 
"Unknown CPLEX basis status";
 
  636    LOG(FATAL) << 
"Basis status only available for continuous problems";
 
  642      CPXDIM 
const rows = CPXXgetnumrows(mEnv, mLp);
 
  643      unique_ptr<int[]> data(
new int[rows]);
 
  651    return xformBasisStatus(mRstat[constraint_index]);
 
  653    LOG(FATAL) << 
"Row basis status not available";
 
 
  661    LOG(FATAL) << 
"Basis status only available for continuous problems";
 
  667      CPXDIM 
const cols = CPXXgetnumcols(mEnv, mLp);
 
  668      unique_ptr<int[]> data(
new int[cols]);
 
  676    return xformBasisStatus(mCstat[variable_index]);
 
  678    LOG(FATAL) << 
"Column basis status not available";
 
 
  690  if (!supportIncrementalExtraction) {
 
  700  int const var_count = 
solver_->variables_.size();
 
  701  CPXDIM newcols = var_count - last_extracted;
 
  705    unique_ptr<double[]> obj(
new double[newcols]);
 
  706    unique_ptr<double[]> lb(
new double[newcols]);
 
  707    unique_ptr<double[]> ub(
new double[newcols]);
 
  708    unique_ptr<char[]> ctype(
new char[newcols]);
 
  709    unique_ptr<const char*[]> colname(
new const char*[newcols]);
 
  711    bool have_names = 
false;
 
  712    for (
int j = 0, varidx = last_extracted; j < newcols; ++j, ++varidx) {
 
  716      ctype[j] = var->
integer() ? CPX_INTEGER : CPX_CONTINUOUS;
 
  717      colname[j] = var->
name().empty() ? 0 : var->
name().c_str();
 
  718      have_names = have_names || var->
name().empty();
 
  719      obj[j] = 
solver_->objective_->GetCoefficient(var);
 
  727    std::vector<MPVariable*> 
const& variables = 
solver_->variables();
 
  728    for (
int j = last_extracted; j < var_count; ++j) {
 
  734      bool use_newcols = 
true;
 
  736      if (supportIncrementalExtraction) {
 
  745        unique_ptr<CPXDIM[]> collen(
new CPXDIM[newcols]);
 
  746        for (CPXDIM j = 0; j < newcols; ++j) collen[j] = 0;
 
  753          const auto& coeffs = ct->coefficients_;
 
  754          for (
auto it(coeffs.begin()); it != coeffs.end(); ++it) {
 
  755            int const idx = it->first->index();
 
  768          unique_ptr<CPXNNZ[]> 
begin(
new CPXNNZ[newcols + 2]);
 
  769          unique_ptr<CPXDIM[]> cmatind(
new CPXDIM[nonzeros]);
 
  770          unique_ptr<double[]> cmatval(
new double[nonzeros]);
 
  781          CPXNNZ* cmatbeg = 
begin.get();
 
  785          for (CPXDIM j = 0; j < newcols; ++j)
 
  786            cmatbeg[j + 1] = cmatbeg[j] + collen[j];
 
  790            CPXDIM 
const row = ct->
index();
 
  791            const auto& coeffs = ct->coefficients_;
 
  792            for (
auto it(coeffs.begin()); it != coeffs.end(); ++it) {
 
  793              int const idx = it->first->index();
 
  795                CPXNNZ 
const nz = cmatbeg[idx]++;
 
  797                cmatval[nz] = it->second;
 
  802          CHECK_STATUS(CPXXaddcols(mEnv, mLp, newcols, nonzeros, obj.get(),
 
  803                                   cmatbeg, cmatind.get(), cmatval.get(),
 
  805                                   have_names ? colname.get() : 0));
 
  812        CHECK_STATUS(CPXXnewcols(mEnv, mLp, newcols, obj.get(), lb.get(),
 
  813                                 ub.get(), mMip ? ctype.get() : 0,
 
  814                                 have_names ? colname.get() : 0));
 
  822          int const cols = CPXXgetnumcols(mEnv, mLp);
 
  823          unique_ptr<CPXDIM[]> ind(
new CPXDIM[newcols]);
 
  824          for (
int j = last_extracted; j < cols; ++j)
 
  825            ind[j - last_extracted] = j;
 
  826          CHECK_STATUS(CPXXchgctype(mEnv, mLp, cols - last_extracted, ind.get(),
 
  832      CPXDIM 
const cols = CPXXgetnumcols(mEnv, mLp);
 
  833      if (cols > last_extracted)
 
  834        (void)CPXXdelcols(mEnv, mLp, last_extracted, cols - 1);
 
  835      std::vector<MPVariable*> 
const& variables = 
solver_->variables();
 
  836      int const size = variables.size();
 
  837      for (
int j = last_extracted; j < size; ++j)
 
 
  849  if (!supportIncrementalExtraction) {
 
  859  CPXDIM 
const total = 
solver_->constraints_.size();
 
  861  if (total > offset) {
 
  866    CPXDIM newCons = total - offset;
 
  867    CPXDIM 
const cols = CPXXgetnumcols(mEnv, mLp);
 
  869    CPXDIM 
const chunk = 10;  
 
  873    for (CPXDIM c = offset; c < total; ++c)
 
  877      unique_ptr<CPXDIM[]> rmatind(
new CPXDIM[cols]);
 
  878      unique_ptr<double[]> rmatval(
new double[cols]);
 
  879      unique_ptr<CPXNNZ[]> rmatbeg(
new CPXNNZ[chunk]);
 
  880      unique_ptr<char[]> sense(
new char[chunk]);
 
  881      unique_ptr<double[]> rhs(
new double[chunk]);
 
  882      unique_ptr<char const*[]> name(
new char const*[chunk]);
 
  883      unique_ptr<double[]> rngval(
new double[chunk]);
 
  884      unique_ptr<CPXDIM[]> rngind(
new CPXDIM[chunk]);
 
  885      bool haveRanges = 
false;
 
  890      for (CPXDIM c = 0; c < newCons; ) {
 
  894        for (; c < newCons && nextRow < chunk; ++c, ++nextRow) {
 
  899          if (nextNz + ct->coefficients_.size() > cols) {
 
  900            DCHECK_GT(nextRow, 0);
 
  905          MakeRhs(ct->
lb(), ct->
ub(), rhs[nextRow], sense[nextRow],
 
  907          haveRanges = haveRanges || (rngval[nextRow] != 0.0);
 
  908          rngind[nextRow] = offset + c;
 
  911          rmatbeg[nextRow] = nextNz;
 
  912          const auto& coeffs = ct->coefficients_;
 
  913          for (
auto it(coeffs.begin()); it != coeffs.end(); ++it) {
 
  914            CPXDIM 
const idx = it->first->index();
 
  916              DCHECK_LT(nextNz, cols);
 
  917              DCHECK_LT(idx, cols);
 
  918              rmatind[nextNz] = idx;
 
  919              rmatval[nextNz] = it->second;
 
  925          name[nextRow] = ct->
name().empty() ? 0 : ct->
name().c_str();
 
  928          CHECK_STATUS(CPXXaddrows(mEnv, mLp, 0, nextRow, nextNz, rhs.get(),
 
  929                                   sense.get(), rmatbeg.get(), rmatind.get(),
 
  930                                   rmatval.get(), 0, name.get()));
 
  933                CPXXchgrngval(mEnv, mLp, nextRow, rngind.get(), rngval.get()));
 
  939      CPXDIM 
const rows = CPXXgetnumrows(mEnv, mLp);
 
  940      if (rows > offset) (void)CPXXdelrows(mEnv, mLp, offset, rows - 1);
 
  941      std::vector<MPConstraint*> 
const& constraints = 
solver_->constraints();
 
  942      int const size = constraints.size();
 
 
  954  CPXDIM 
const cols = CPXXgetnumcols(mEnv, mLp);
 
  957  unique_ptr<CPXDIM[]> ind(
new CPXDIM[cols]);
 
  958  unique_ptr<double[]> val(
new double[cols]);
 
  959  for (CPXDIM j = 0; j < cols; ++j) {
 
  964  const auto& coeffs = 
solver_->objective_->coefficients_;
 
  965  for (
auto it = coeffs.begin(); it != coeffs.end(); ++it) {
 
  966    CPXDIM 
const idx = it->first->index();
 
  968      DCHECK_LT(idx, cols);
 
  969      val[idx] = it->second;
 
  973  CHECK_STATUS(CPXXchgobj(mEnv, mLp, cols, ind.get(), val.get()));
 
 
  986    CHECK_STATUS(CPXXsetdblparam(mEnv, CPX_PARAM_EPGAP, value));
 
  988    LOG(WARNING) << 
"The relative MIP gap is only available " 
  989                 << 
"for discrete problems.";
 
 
  994  CHECK_STATUS(CPXXsetdblparam(mEnv, CPX_PARAM_EPRHS, value));
 
 
  998  CHECK_STATUS(CPXXsetdblparam(mEnv, CPX_PARAM_EPOPT, value));
 
 
 1007      CHECK_STATUS(CPXXsetintparam(mEnv, CPX_PARAM_PREIND, CPX_OFF));
 
 1010      CHECK_STATUS(CPXXsetintparam(mEnv, CPX_PARAM_PREIND, CPX_ON));
 
 
 1023      CHECK_STATUS(CPXXsetintparam(mEnv, CPX_PARAM_SCAIND, -1));
 
 1028      CHECK_STATUS(CPXXsetintparam(mEnv, CPX_PARAM_SCAIND, 0));
 
 
 1039  int alg = CPX_ALG_NONE;
 
 1041  switch (algorithm) {
 
 1046      alg = CPX_ALG_PRIMAL;
 
 1049      alg = CPX_ALG_BARRIER;
 
 1053  if (alg == CPX_ALG_NONE)
 
 1056    CHECK_STATUS(CPXXsetintparam(mEnv, CPX_PARAM_LPMETHOD, alg));
 
 1060      CHECK_STATUS(CPXXsetintparam(mEnv, CPX_PARAM_STARTALG, alg));
 
 1061      CHECK_STATUS(CPXXsetintparam(mEnv, CPX_PARAM_SUBALG, alg));
 
 
 1068  return CPXXreadcopyparam(mEnv, filename.c_str()) == 0;
 
 
 1093      CHECK_STATUS(CPXXsetintparam(mEnv, CPX_PARAM_ADVIND, 0));
 
 1096      CHECK_STATUS(CPXXsetintparam(mEnv, CPX_PARAM_ADVIND, 2));
 
 1107  VLOG(1) << absl::StrFormat(
"Model build in %.3f seconds.", timer.
Get());
 
 1111      CPXXsetintparam(mEnv, CPX_PARAM_SCRIND, 
quiet() ? CPX_OFF : CPX_ON));
 
 1113  if (!
solver_->solution_hint_.empty()) {
 
 1114    int const sol_count = 
solver_->solution_hint_.size();
 
 1115    long long int beg[1] = {0};
 
 1116    int* varindices = 
new int[sol_count];
 
 1117    double* values = 
new double[sol_count];
 
 1119    for (
int i = 0; i < sol_count; ++i) {
 
 1120      varindices[i] = 
solver_->solution_hint_[i].first->index();
 
 1121      values[i] = 
solver_->solution_hint_[i].second;
 
 1123    CPXXaddmipstarts(mEnv, mLp, 1, sol_count, beg, varindices, values, NULL,
 
 1131  solver_->SetSolverSpecificParametersAsString(
 
 1132      solver_->solver_specific_parameter_string_);
 
 1135    VLOG(1) << 
"Setting time limit = " << 
solver_->time_limit() << 
" ms.";
 
 1137        CPXXsetdblparam(mEnv, CPX_PARAM_TILIM, 
solver_->time_limit() * 1e-3));
 
 1145    status = CPXXmipopt(mEnv, mLp);
 
 1147    status = CPXXlpopt(mEnv, mLp);
 
 1151  (void)CPXXsetintparam(mEnv, CPX_PARAM_SCRIND, CPX_OFF);
 
 1154    VLOG(1) << absl::StrFormat(
"Failed to optimize MIP. Error %d", status);
 
 1158    VLOG(1) << absl::StrFormat(
"Solved in %.3f seconds.", timer.
Get());
 
 1161  int const cpxstat = CPXXgetstat(mEnv, mLp);
 
 1162  VLOG(1) << absl::StrFormat(
"CPLEX solution status %d.", cpxstat);
 
 1165  int solnmethod, solntype, pfeas, dfeas;
 
 1166  CHECK_STATUS(CPXXsolninfo(mEnv, mLp, &solnmethod, &solntype, &pfeas, &dfeas));
 
 1167  bool const feasible = pfeas != 0;
 
 1170  CPXDIM 
const rows = CPXXgetnumrows(mEnv, mLp);
 
 1171  CPXDIM 
const cols = CPXXgetnumcols(mEnv, mLp);
 
 1172  DCHECK_EQ(rows, 
solver_->constraints_.size());
 
 1173  DCHECK_EQ(cols, 
solver_->variables_.size());
 
 1192        unique_ptr<double[]> x(
new double[cols]);
 
 1193        CHECK_STATUS(CPXXgetx(mEnv, mLp, x.get(), 0, cols - 1));
 
 1194        for (
int i = 0; i < 
solver_->variables_.size(); ++i) {
 
 1197          VLOG(3) << var->
name() << 
": value =" << x[i];
 
 1201      for (
int i = 0; i < 
solver_->variables_.size(); ++i)
 
 1206    for (
int i = 0; i < 
solver_->variables_.size(); ++i)
 
 1208    for (
int i = 0; i < 
solver_->constraints_.size(); ++i)
 
 1213      unique_ptr<double[]> x(
new double[cols]);
 
 1214      unique_ptr<double[]> dj(
new double[cols]);
 
 1215      if (feasible) 
CHECK_STATUS(CPXXgetx(mEnv, mLp, x.get(), 0, cols - 1));
 
 1216      if (dfeas) 
CHECK_STATUS(CPXXgetdj(mEnv, mLp, dj.get(), 0, cols - 1));
 
 1217      for (
int i = 0; i < 
solver_->variables_.size(); ++i) {
 
 1220        bool value = 
false, dual = 
false;
 
 1232        VLOG(3) << var->
name() << 
":" 
 1233                << (value ? absl::StrFormat(
"  value = %f", x[i]) : 
"")
 
 1234                << (dual ? absl::StrFormat(
"  reduced cost = %f", dj[i]) : 
"");
 
 1239      unique_ptr<double[]> pi(
new double[rows]);
 
 1240      if (dfeas) 
CHECK_STATUS(CPXXgetpi(mEnv, mLp, pi.get(), 0, rows - 1));
 
 1241      for (
int i = 0; i < 
solver_->constraints_.size(); ++i) {
 
 1249        VLOG(4) << 
"row " << ct->
index() << 
":" 
 1250                << (dual ? absl::StrFormat(
"  dual = %f", pi[i]) : 
"");
 
 1257    case CPX_STAT_OPTIMAL:
 
 1258    case CPXMIP_OPTIMAL:
 
 1261    case CPXMIP_OPTIMAL_TOL:
 
 1265    case CPX_STAT_INFEASIBLE:
 
 1266    case CPXMIP_INFEASIBLE:
 
 1269    case CPX_STAT_UNBOUNDED:
 
 1270    case CPXMIP_UNBOUNDED:
 
 1273    case CPX_STAT_INForUNBD:
 
 1274    case CPXMIP_INForUNBD:
 
 
 1291    const std::string& parameters) {
 
 1292  if (parameters.empty()) 
return true;
 
 1293  for (
const auto parameter : absl::StrSplit(parameters, absl::ByAnyChar(
","),
 
 1294                                             absl::SkipWhitespace())) {
 
 1295    std::vector<std::string> key_value =
 
 1296        absl::StrSplit(parameter, absl::ByAnyChar(
"="), absl::SkipWhitespace());
 
 1297    if (key_value.size() != 2) {
 
 1298      LOG(WARNING) << absl::StrFormat(
 
 1299          "Cannot parse parameter '%s'. Expected format is 'parameter/name = " 
 1304    std::string identifier = key_value[0];
 
 1305    absl::RemoveExtraAsciiWhitespace(&identifier);
 
 1307    std::string value = key_value[1];
 
 1308    absl::RemoveExtraAsciiWhitespace(&value);
 
 1311      if (identifier.find(
"LogFile") != std::string::npos) {
 
 1312        CPXXsetlogfilename(mEnv, value.c_str(), 
"w");
 
 1314        std::string delimiter = 
".";
 
 1315        if (value.find(delimiter) == std::string::npos) {
 
 1316          (void)CPXXsetintparam(mEnv, std::stoi(identifier), std::stoi(value));
 
 1318          (void)CPXXsetdblparam(mEnv, std::stoi(identifier), std::stod(value));
 
 1320        VLOG(2) << absl::StrFormat(
"Set parameter %s to %s", identifier, value);
 
 1323      LOG(WARNING) << absl::StrFormat(
 
 1324          "Cannot parse parameter '%s'. Expected format is 'parameter/name = " 
 
void Start()
When Start() is called multiple times, only the most recent is used.
virtual MPSolver::BasisStatus row_status(int constraint_index) const
Returns the basis status of a row.
virtual void SetOptimizationDirection(bool maximize)
Sets the optimization direction (min/max).
virtual MPSolver::BasisStatus column_status(int variable_index) const
Returns the basis status of a column.
virtual int64_t iterations() const
---— Query statistics on the solution and the solve ---—
bool SetSolverSpecificParametersAsString(const std::string ¶meters) override
virtual double ComputeExactConditionNumber() const
virtual void SetVariableBounds(int var_index, double lb, double ub)
Modifies bounds of an extracted variable.
virtual void * underlying_solver()
Returns the underlying solver.
virtual void ClearObjective()
Clear the objective from all its terms.
virtual void Reset()
---— Model modifications and extraction --—
virtual void AddRowConstraint(MPConstraint *const ct)
Adds a linear constraint.
virtual void ClearConstraint(MPConstraint *const constraint)
Clear a constraint from all its terms.
virtual void ExtractNewVariables()
Extract all variables that have not yet been extracted.
virtual void SetVariableInteger(int var_index, bool integer)
Modifies integrality of an extracted variable.
virtual MPSolver::ResultStatus Solve(MPSolverParameters const ¶m)
virtual void SetCoefficient(MPConstraint *const constraint, MPVariable const *const variable, double new_value, double old_value)
Changes a coefficient in a constraint.
virtual std::string SolverVersion() const
Returns a string describing the underlying solver and its version.
virtual void SetPresolveMode(int value)
virtual int64_t nodes() const
Number of branch-and-bound nodes. Only available for discrete problems.
virtual bool ReadParameterFile(std::string const &filename)
virtual void SetParameters(MPSolverParameters const ¶m)
Set all parameters in the underlying solver.
virtual bool IsContinuous() const
--— Misc --—
virtual void SetObjectiveOffset(double value)
Change the constant term in the linear objective.
virtual void AddVariable(MPVariable *const var)
Add a variable.
virtual void ExtractNewConstraints()
Extract constraints that have not yet been extracted.
virtual bool IsLP() const
Returns true if the problem is continuous and linear.
virtual void SetConstraintBounds(int row_index, double lb, double ub)
Modify bounds of an extracted variable.
virtual void SetLpAlgorithm(int value)
virtual bool IsMIP() const
Returns true if the problem is discrete and linear.
virtual void SetScalingMode(int value)
Sets the scaling mode.
virtual void ExtractObjective()
Extract the objective function.
virtual void SetObjectiveCoefficient(MPVariable const *const variable, double coefficient)
Change a coefficient in the linear objective.
virtual void SetDualTolerance(double value)
CplexInterface(MPSolver *const solver, bool mip)
Creates a LP/MIP instance.
virtual std::string ValidFileExtensionForParameterFile() const
virtual void SetRelativeMipGap(double value)
Set each parameter in the underlying solver.
virtual void SetPrimalTolerance(double value)
void set_dual_value(double dual_value)
double lb() const
Returns the lower bound.
double ub() const
Returns the upper bound.
const std::string & name() const
Returns the name of the constraint.
int index() const
Returns the index of the constraint in the MPSolver::constraints_.
void set_variable_as_extracted(int var_index, bool extracted)
bool CheckSolutionIsSynchronized() const
static constexpr int64_t kUnknownNumberOfIterations
friend class MPConstraint
To access the maximize_ bool and the MPSolver.
void InvalidateSolutionSynchronization()
void set_constraint_as_extracted(int ct_index, bool extracted)
void ResetExtractionInformation()
Resets the extraction information.
int last_variable_index_
Index in MPSolver::constraints_ of last variable extracted.
virtual void SetIntegerParamToUnsupportedValue(MPSolverParameters::IntegerParam param, int value)
Sets a supported integer parameter to an unsupported value.
int last_constraint_index_
Index in MPSolver::variables_ of last constraint extracted.
bool variable_is_extracted(int var_index) const
bool quiet() const
Returns the boolean indicating the verbosity of the solver output.
bool constraint_is_extracted(int ct_index) const
static constexpr int64_t kUnknownNumberOfNodes
void ExtractModel()
Extracts model stored in MPSolver.
double objective_value_
The value of the objective function.
double best_objective_bound_
The value of the best objective bound. Used only for MIP solvers.
bool maximize_
Optimization direction.
void SetMIPParameters(const MPSolverParameters ¶m)
Sets MIP specific parameters in the underlying solver.
MPSolverInterface(MPSolver *solver)
void SetCommonParameters(const MPSolverParameters ¶m)
Sets parameters common to LP and MIP in the underlying solver.
MPSolver::ResultStatus result_status_
SynchronizationStatus sync_status_
Indicates whether the model and the solution are synchronized.
PresolveValues
For each categorical parameter, enumeration of possible values.
@ PRESOLVE_OFF
Presolve is off.
@ PRESOLVE_ON
Presolve is on.
LpAlgorithmValues
LP algorithm to use.
@ BARRIER
Barrier algorithm.
@ INCREMENTALITY
Advanced usage: incrementality from one solve to the next.
@ PRESOLVE
Advanced usage: presolve mode.
@ LP_ALGORITHM
Algorithm to solve linear programs.
IncrementalityValues
Advanced usage: Incrementality options.
@ INCREMENTALITY_OFF
Start solve from scratch.
ScalingValues
Advanced usage: Scaling options.
@ SCALING_ON
Scaling is on.
@ SCALING_OFF
Scaling is off.
int GetIntegerParam(MPSolverParameters::IntegerParam param) const
Returns the value of an integer parameter.
@ FEASIBLE
feasible, or stopped by limit.
@ INFEASIBLE
proven infeasible.
@ UNBOUNDED
proven unbounded.
@ ABNORMAL
abnormal, i.e., error of some kind.
The class for variables of a Mathematical Programming (MP) model.
bool integer() const
Returns the integrality requirement of the variable.
double lb() const
Returns the lower bound.
double ub() const
Returns the upper bound.
const std::string & name() const
Returns the name of the variable.
void set_reduced_cost(double reduced_cost)
void set_solution_value(double value)
int index() const
Returns the index of the variable in the MPSolver::variables_.
CPXLIBAPI int CPXPUBLIC CPXEsetobjoffset(CPXCENVptr, CPXLPptr, double)
Initial version of this code was written by Daniel Junglas (IBM)
In SWIG mode, we don't want anything besides these top-level includes.
ClosedInterval::Iterator begin(ClosedInterval interval)
MPSolverInterface * BuildCplexInterface(bool mip, MPSolver *const solver)