19#include "absl/strings/str_format.h"
20#include "absl/strings/str_split.h"
26#include "ilcplex/cplexx.h"
36#define CPX_NAN std::numeric_limits<double>::quiet_NaN()
42#define CHECK_STATUS(s) \
44 int const status_ = s; \
45 CHECK_EQ(0, status_); \
84 double new_value,
double old_value);
100 virtual int64_t
nodes()
const;
113 virtual bool IsLP()
const {
return !mMip; }
114 virtual bool IsMIP()
const {
return mMip; }
117 const std::string& parameters)
override;
128 LOG(DFATAL) <<
"ComputeExactConditionNumber not implemented for"
129 <<
" CPLEX_MIXED_INTEGER_PROGRAMMING";
135 CHECK_STATUS(CPXXgetdblquality(mEnv, mLp, &kappa, CPX_EXACT_KAPPA));
138 LOG(DFATAL) <<
"Cannot get exact condition number without solution";
160 void InvalidateModelSynchronization() {
184 bool const supportIncrementalExtraction;
192 SlowSetCoefficient = 0x0001,
193 SlowClearConstraint = 0x0002,
194 SlowSetObjectiveCoefficient = 0x0004,
195 SlowClearObjective = 0x0008,
196 SlowSetConstraintBounds = 0x0010,
197 SlowSetVariableInteger = 0x0020,
198 SlowSetVariableBounds = 0x0040,
199 SlowUpdatesAll = 0xffff
205 unique_ptr<int[]>
mutable mCstat;
206 unique_ptr<int[]>
mutable mRstat;
209 static void MakeRhs(
double lb,
double ub,
double& rhs,
char& sense,
219 slowUpdates(static_cast<SlowUpdates>(SlowSetObjectiveCoefficient |
220 SlowClearObjective)),
221 supportIncrementalExtraction(false),
226 mEnv = CPXXopenCPLEX(&status);
228 DCHECK(mEnv !=
nullptr);
230 char const* name =
solver_->name_.c_str();
231 mLp = CPXXcreateprob(mEnv, &status, name);
233 DCHECK(mLp !=
nullptr);
236 if (mMip)
CHECK_STATUS(CPXXchgprobtype(mEnv, mLp, CPXPROB_MILP));
250 int const major = version / 1000000;
251 version -= major * 1000000;
252 int const release = version / 10000;
253 version -= release * 10000;
254 int const mod = version / 100;
255 version -= mod * 100;
256 int const fix = version;
258 return absl::StrFormat(
"CPLEX library version %d.%02d.%02d.%02d", major,
270 const char*
const name =
solver_->name_.c_str();
271 mLp = CPXXcreateprob(mEnv, &status, name);
273 DCHECK(mLp !=
nullptr);
276 if (mMip)
CHECK_STATUS(CPXXchgprobtype(mEnv, mLp, CPXPROB_MILP));
285 CPXXchgobjsen(mEnv, mLp, maximize ? CPX_MAX : CPX_MIN);
297 if (!supportIncrementalExtraction && !(slowUpdates & SlowSetVariableBounds)) {
298 InvalidateModelSynchronization();
304 char const lu[2] = {
'L',
'U'};
305 double const bd[2] = {lb, ub};
306 CPXDIM
const idx[2] = {var_index, var_index};
311 InvalidateModelSynchronization();
330 if (!supportIncrementalExtraction &&
331 !(slowUpdates && SlowSetVariableInteger)) {
332 InvalidateModelSynchronization();
339 DCHECK_LE(var_index, CPXXgetnumcols(mEnv, mLp));
340 char const type = integer ? CPX_INTEGER : CPX_CONTINUOUS;
341 CHECK_STATUS(CPXXchgctype(mEnv, mLp, 1, &var_index, &type));
343 InvalidateModelSynchronization();
346 <<
"Attempt to change variable to integer in non-MIP problem!";
352void CplexInterface::MakeRhs(
double lb,
double ub,
double& rhs,
char& sense,
359 }
else if (lb > -CPX_INFBOUND && ub < CPX_INFBOUND) {
379 }
else if (ub < CPX_INFBOUND ||
380 (std::abs(ub) == CPX_INFBOUND && std::abs(lb) > CPX_INFBOUND)) {
385 }
else if (lb > -CPX_INFBOUND ||
386 (std::abs(lb) == CPX_INFBOUND && std::abs(ub) > CPX_INFBOUND)) {
400 DCHECK_GT(std::abs(lb), CPX_INFBOUND);
401 DCHECK_GT(std::abs(ub), CPX_INFBOUND);
402 if (std::abs(lb) > std::abs(ub)) {
403 rhs = (lb < 0) ? -CPX_INFBOUND : CPX_INFBOUND;
406 rhs = (ub < 0) ? -CPX_INFBOUND : CPX_INFBOUND;
422 if (!supportIncrementalExtraction &&
423 !(slowUpdates & SlowSetConstraintBounds)) {
424 InvalidateModelSynchronization();
432 MakeRhs(lb, ub, rhs, sense, range);
434 CHECK_STATUS(CPXXchgsense(mEnv, mLp, 1, &index, &sense));
435 CHECK_STATUS(CPXXchgrngval(mEnv, mLp, 1, &index, &range));
439 InvalidateModelSynchronization();
451 InvalidateModelSynchronization();
461 InvalidateModelSynchronization();
466 double new_value,
double) {
476 if (!supportIncrementalExtraction && !(slowUpdates & SlowSetCoefficient)) {
477 InvalidateModelSynchronization();
479 int const row = constraint->
index();
480 int const col = variable->
index();
486 CHECK_STATUS(CPXXchgcoef(mEnv, mLp, row, col, new_value));
490 InvalidateModelSynchronization();
496 CPXDIM
const row = constraint->
index();
509 if (!(slowUpdates & SlowClearConstraint)) {
510 InvalidateModelSynchronization();
514 CPXDIM
const len = constraint->coefficients_.size();
515 unique_ptr<CPXDIM[]> rowind(
new CPXDIM[len]);
516 unique_ptr<CPXDIM[]> colind(
new CPXDIM[len]);
517 unique_ptr<double[]> val(
new double[len]);
519 const auto& coeffs = constraint->coefficients_;
520 for (
auto it(coeffs.begin()); it != coeffs.end(); ++it) {
521 CPXDIM
const col = it->first->index();
531 CPXXchgcoeflist(mEnv, mLp, j, rowind.get(), colind.get(), val.get()));
536 double coefficient) {
537 CPXDIM
const col = variable->
index();
550 if (supportIncrementalExtraction ||
551 (slowUpdates & SlowSetObjectiveCoefficient)) {
552 CHECK_STATUS(CPXXchgobj(mEnv, mLp, 1, &col, &coefficient));
554 InvalidateModelSynchronization();
571 if (supportIncrementalExtraction || (slowUpdates & SlowClearObjective)) {
572 CPXDIM
const cols = CPXXgetnumcols(mEnv, mLp);
573 unique_ptr<CPXDIM[]> ind(
new CPXDIM[cols]);
574 unique_ptr<double[]> zero(
new double[cols]);
576 const auto& coeffs =
solver_->objective_->coefficients_;
577 for (
auto it(coeffs.begin()); it != coeffs.end(); ++it) {
578 CPXDIM
const idx = it->first->index();
581 DCHECK_LT(idx, cols);
587 if (j > 0)
CHECK_STATUS(CPXXchgobj(mEnv, mLp, j, ind.get(), zero.get()));
590 InvalidateModelSynchronization();
599 return static_cast<int64_t
>(CPXXgetmipitcnt(mEnv, mLp));
601 return static_cast<int64_t
>(CPXXgetitcnt(mEnv, mLp));
607 return static_cast<int64_t
>(CPXXgetnodecnt(mEnv, mLp));
609 LOG(DFATAL) <<
"Number of nodes only available for discrete problems";
616 switch (cplex_basis_status) {
626 LOG(DFATAL) <<
"Unknown CPLEX basis status";
634 LOG(FATAL) <<
"Basis status only available for continuous problems";
640 CPXDIM
const rows = CPXXgetnumrows(mEnv, mLp);
641 unique_ptr<int[]> data(
new int[rows]);
649 return xformBasisStatus(mRstat[constraint_index]);
651 LOG(FATAL) <<
"Row basis status not available";
659 LOG(FATAL) <<
"Basis status only available for continuous problems";
665 CPXDIM
const cols = CPXXgetnumcols(mEnv, mLp);
666 unique_ptr<int[]> data(
new int[cols]);
674 return xformBasisStatus(mCstat[variable_index]);
676 LOG(FATAL) <<
"Column basis status not available";
688 if (!supportIncrementalExtraction) {
698 int const var_count =
solver_->variables_.size();
699 CPXDIM newcols = var_count - last_extracted;
703 unique_ptr<double[]> obj(
new double[newcols]);
704 unique_ptr<double[]> lb(
new double[newcols]);
705 unique_ptr<double[]> ub(
new double[newcols]);
706 unique_ptr<char[]> ctype(
new char[newcols]);
707 unique_ptr<const char*[]> colname(
new const char*[newcols]);
709 bool have_names =
false;
710 for (
int j = 0, varidx = last_extracted; j < newcols; ++j, ++varidx) {
714 ctype[j] = var->
integer() ? CPX_INTEGER : CPX_CONTINUOUS;
715 colname[j] = var->
name().empty() ? 0 : var->
name().c_str();
716 have_names = have_names || var->
name().empty();
717 obj[j] =
solver_->objective_->GetCoefficient(var);
725 std::vector<MPVariable*>
const& variables =
solver_->variables();
726 for (
int j = last_extracted; j < var_count; ++j) {
732 bool use_newcols =
true;
734 if (supportIncrementalExtraction) {
743 unique_ptr<CPXDIM[]> collen(
new CPXDIM[newcols]);
744 for (CPXDIM j = 0; j < newcols; ++j) collen[j] = 0;
751 const auto& coeffs = ct->coefficients_;
752 for (
auto it(coeffs.begin()); it != coeffs.end(); ++it) {
753 int const idx = it->first->index();
766 unique_ptr<CPXNNZ[]>
begin(
new CPXNNZ[newcols + 2]);
767 unique_ptr<CPXDIM[]> cmatind(
new CPXDIM[nonzeros]);
768 unique_ptr<double[]> cmatval(
new double[nonzeros]);
779 CPXNNZ* cmatbeg =
begin.get();
783 for (CPXDIM j = 0; j < newcols; ++j)
784 cmatbeg[j + 1] = cmatbeg[j] + collen[j];
788 CPXDIM
const row = ct->
index();
789 const auto& coeffs = ct->coefficients_;
790 for (
auto it(coeffs.begin()); it != coeffs.end(); ++it) {
791 int const idx = it->first->index();
793 CPXNNZ
const nz = cmatbeg[idx]++;
795 cmatval[nz] = it->second;
800 CHECK_STATUS(CPXXaddcols(mEnv, mLp, newcols, nonzeros, obj.get(),
801 cmatbeg, cmatind.get(), cmatval.get(),
803 have_names ? colname.get() : 0));
810 CHECK_STATUS(CPXXnewcols(mEnv, mLp, newcols, obj.get(), lb.get(),
811 ub.get(), mMip ? ctype.get() : 0,
812 have_names ? colname.get() : 0));
820 int const cols = CPXXgetnumcols(mEnv, mLp);
821 unique_ptr<CPXDIM[]> ind(
new CPXDIM[newcols]);
822 for (
int j = last_extracted; j < cols; ++j)
823 ind[j - last_extracted] = j;
824 CHECK_STATUS(CPXXchgctype(mEnv, mLp, cols - last_extracted, ind.get(),
830 CPXDIM
const cols = CPXXgetnumcols(mEnv, mLp);
831 if (cols > last_extracted)
832 (void)CPXXdelcols(mEnv, mLp, last_extracted, cols - 1);
833 std::vector<MPVariable*>
const& variables =
solver_->variables();
834 int const size = variables.size();
835 for (
int j = last_extracted; j < size; ++j)
847 if (!supportIncrementalExtraction) {
857 CPXDIM
const total =
solver_->constraints_.size();
859 if (total > offset) {
864 CPXDIM newCons = total - offset;
865 CPXDIM
const cols = CPXXgetnumcols(mEnv, mLp);
867 CPXDIM
const chunk = 10;
871 for (CPXDIM c = offset; c < total; ++c)
875 unique_ptr<CPXDIM[]> rmatind(
new CPXDIM[cols]);
876 unique_ptr<double[]> rmatval(
new double[cols]);
877 unique_ptr<CPXNNZ[]> rmatbeg(
new CPXNNZ[chunk]);
878 unique_ptr<char[]> sense(
new char[chunk]);
879 unique_ptr<double[]> rhs(
new double[chunk]);
880 unique_ptr<char const*[]> name(
new char const*[chunk]);
881 unique_ptr<double[]> rngval(
new double[chunk]);
882 unique_ptr<CPXDIM[]> rngind(
new CPXDIM[chunk]);
883 bool haveRanges =
false;
888 for (CPXDIM c = 0; c < newCons; ) {
892 for (; c < newCons && nextRow < chunk; ++c, ++nextRow) {
897 if (nextNz + ct->coefficients_.size() > cols) {
898 DCHECK_GT(nextRow, 0);
903 MakeRhs(ct->
lb(), ct->
ub(), rhs[nextRow], sense[nextRow],
905 haveRanges = haveRanges || (rngval[nextRow] != 0.0);
906 rngind[nextRow] = offset + c;
909 rmatbeg[nextRow] = nextNz;
910 const auto& coeffs = ct->coefficients_;
911 for (
auto it(coeffs.begin()); it != coeffs.end(); ++it) {
912 CPXDIM
const idx = it->first->index();
914 DCHECK_LT(nextNz, cols);
915 DCHECK_LT(idx, cols);
916 rmatind[nextNz] = idx;
917 rmatval[nextNz] = it->second;
923 name[nextRow] = ct->
name().empty() ? 0 : ct->
name().c_str();
926 CHECK_STATUS(CPXXaddrows(mEnv, mLp, 0, nextRow, nextNz, rhs.get(),
927 sense.get(), rmatbeg.get(), rmatind.get(),
928 rmatval.get(), 0, name.get()));
931 CPXXchgrngval(mEnv, mLp, nextRow, rngind.get(), rngval.get()));
937 CPXDIM
const rows = CPXXgetnumrows(mEnv, mLp);
938 if (rows > offset) (void)CPXXdelrows(mEnv, mLp, offset, rows - 1);
939 std::vector<MPConstraint*>
const& constraints =
solver_->constraints();
940 int const size = constraints.size();
952 CPXDIM
const cols = CPXXgetnumcols(mEnv, mLp);
955 unique_ptr<CPXDIM[]> ind(
new CPXDIM[cols]);
956 unique_ptr<double[]> val(
new double[cols]);
957 for (CPXDIM j = 0; j < cols; ++j) {
962 const auto& coeffs =
solver_->objective_->coefficients_;
963 for (
auto it = coeffs.begin(); it != coeffs.end(); ++it) {
964 CPXDIM
const idx = it->first->index();
966 DCHECK_LT(idx, cols);
967 val[idx] = it->second;
971 CHECK_STATUS(CPXXchgobj(mEnv, mLp, cols, ind.get(), val.get()));
984 CHECK_STATUS(CPXXsetdblparam(mEnv, CPX_PARAM_EPGAP, value));
986 LOG(WARNING) <<
"The relative MIP gap is only available "
987 <<
"for discrete problems.";
992 CHECK_STATUS(CPXXsetdblparam(mEnv, CPX_PARAM_EPRHS, value));
996 CHECK_STATUS(CPXXsetdblparam(mEnv, CPX_PARAM_EPOPT, value));
1005 CHECK_STATUS(CPXXsetintparam(mEnv, CPX_PARAM_PREIND, CPX_OFF));
1008 CHECK_STATUS(CPXXsetintparam(mEnv, CPX_PARAM_PREIND, CPX_ON));
1021 CHECK_STATUS(CPXXsetintparam(mEnv, CPX_PARAM_SCAIND, -1));
1026 CHECK_STATUS(CPXXsetintparam(mEnv, CPX_PARAM_SCAIND, 0));
1037 int alg = CPX_ALG_NONE;
1039 switch (algorithm) {
1044 alg = CPX_ALG_PRIMAL;
1047 alg = CPX_ALG_BARRIER;
1051 if (alg == CPX_ALG_NONE)
1054 CHECK_STATUS(CPXXsetintparam(mEnv, CPX_PARAM_LPMETHOD, alg));
1058 CHECK_STATUS(CPXXsetintparam(mEnv, CPX_PARAM_STARTALG, alg));
1059 CHECK_STATUS(CPXXsetintparam(mEnv, CPX_PARAM_SUBALG, alg));
1066 return CPXXreadcopyparam(mEnv, filename.c_str()) == 0;
1091 CHECK_STATUS(CPXXsetintparam(mEnv, CPX_PARAM_ADVIND, 0));
1094 CHECK_STATUS(CPXXsetintparam(mEnv, CPX_PARAM_ADVIND, 2));
1105 VLOG(1) << absl::StrFormat(
"Model build in %.3f seconds.", timer.
Get());
1109 CPXXsetintparam(mEnv, CPX_PARAM_SCRIND,
quiet() ? CPX_OFF : CPX_ON));
1111 if (!
solver_->solution_hint_.empty()) {
1112 int const sol_count =
solver_->solution_hint_.size();
1113 long long int beg[1] = {0};
1114 int* varindices =
new int[sol_count];
1115 double* values =
new double[sol_count];
1117 for (
int i = 0; i < sol_count; ++i) {
1118 varindices[i] =
solver_->solution_hint_[i].first->index();
1119 values[i] =
solver_->solution_hint_[i].second;
1121 CPXXaddmipstarts(mEnv, mLp, 1, sol_count, beg, varindices, values, NULL,
1129 solver_->SetSolverSpecificParametersAsString(
1130 solver_->solver_specific_parameter_string_);
1133 VLOG(1) <<
"Setting time limit = " <<
solver_->time_limit() <<
" ms.";
1135 CPXXsetdblparam(mEnv, CPX_PARAM_TILIM,
solver_->time_limit() * 1e-3));
1143 status = CPXXmipopt(mEnv, mLp);
1145 status = CPXXlpopt(mEnv, mLp);
1149 (void)CPXXsetintparam(mEnv, CPX_PARAM_SCRIND, CPX_OFF);
1152 VLOG(1) << absl::StrFormat(
"Failed to optimize MIP. Error %d", status);
1156 VLOG(1) << absl::StrFormat(
"Solved in %.3f seconds.", timer.
Get());
1159 int const cpxstat = CPXXgetstat(mEnv, mLp);
1160 VLOG(1) << absl::StrFormat(
"CPLEX solution status %d.", cpxstat);
1163 int solnmethod, solntype, pfeas, dfeas;
1164 CHECK_STATUS(CPXXsolninfo(mEnv, mLp, &solnmethod, &solntype, &pfeas, &dfeas));
1165 bool const feasible = pfeas != 0;
1168 CPXDIM
const rows = CPXXgetnumrows(mEnv, mLp);
1169 CPXDIM
const cols = CPXXgetnumcols(mEnv, mLp);
1170 DCHECK_EQ(rows,
solver_->constraints_.size());
1171 DCHECK_EQ(cols,
solver_->variables_.size());
1190 unique_ptr<double[]> x(
new double[cols]);
1191 CHECK_STATUS(CPXXgetx(mEnv, mLp, x.get(), 0, cols - 1));
1192 for (
int i = 0; i <
solver_->variables_.size(); ++i) {
1195 VLOG(3) << var->
name() <<
": value =" << x[i];
1199 for (
int i = 0; i <
solver_->variables_.size(); ++i)
1204 for (
int i = 0; i <
solver_->variables_.size(); ++i)
1206 for (
int i = 0; i <
solver_->constraints_.size(); ++i)
1211 unique_ptr<double[]> x(
new double[cols]);
1212 unique_ptr<double[]> dj(
new double[cols]);
1213 if (feasible)
CHECK_STATUS(CPXXgetx(mEnv, mLp, x.get(), 0, cols - 1));
1214 if (dfeas)
CHECK_STATUS(CPXXgetdj(mEnv, mLp, dj.get(), 0, cols - 1));
1215 for (
int i = 0; i <
solver_->variables_.size(); ++i) {
1218 bool value =
false, dual =
false;
1230 VLOG(3) << var->
name() <<
":"
1231 << (value ? absl::StrFormat(
" value = %f", x[i]) :
"")
1232 << (dual ? absl::StrFormat(
" reduced cost = %f", dj[i]) :
"");
1237 unique_ptr<double[]> pi(
new double[rows]);
1238 if (dfeas)
CHECK_STATUS(CPXXgetpi(mEnv, mLp, pi.get(), 0, rows - 1));
1239 for (
int i = 0; i <
solver_->constraints_.size(); ++i) {
1247 VLOG(4) <<
"row " << ct->
index() <<
":"
1248 << (dual ? absl::StrFormat(
" dual = %f", pi[i]) :
"");
1255 case CPX_STAT_OPTIMAL:
1256 case CPXMIP_OPTIMAL:
1259 case CPXMIP_OPTIMAL_TOL:
1263 case CPX_STAT_INFEASIBLE:
1264 case CPXMIP_INFEASIBLE:
1267 case CPX_STAT_UNBOUNDED:
1268 case CPXMIP_UNBOUNDED:
1271 case CPX_STAT_INForUNBD:
1272 case CPXMIP_INForUNBD:
1284 const std::string& parameters) {
1285 if (parameters.empty())
return true;
1286 for (
const auto parameter : absl::StrSplit(parameters, absl::ByAnyChar(
","),
1287 absl::SkipWhitespace())) {
1288 std::vector<std::string> key_value =
1289 absl::StrSplit(parameter, absl::ByAnyChar(
"="), absl::SkipWhitespace());
1290 if (key_value.size() != 2) {
1291 LOG(WARNING) << absl::StrFormat(
1292 "Cannot parse parameter '%s'. Expected format is 'parameter/name = "
1297 std::string identifier = key_value[0];
1298 absl::RemoveExtraAsciiWhitespace(&identifier);
1300 std::string value = key_value[1];
1301 absl::RemoveExtraAsciiWhitespace(&value);
1304 if (identifier.find(
"LogFile") != std::string::npos) {
1305 CPXXsetlogfilename(mEnv, value.c_str(),
"w");
1307 std::string delimiter =
".";
1308 if (value.find(delimiter) == std::string::npos) {
1309 (void)CPXXsetintparam(mEnv, std::stoi(identifier), std::stoi(value));
1311 (void)CPXXsetdblparam(mEnv, std::stoi(identifier), std::stod(value));
1313 VLOG(2) << absl::StrFormat(
"Set parameter %s to %s", identifier, value);
1316 LOG(WARNING) << absl::StrFormat(
1317 "Cannot parse parameter '%s'. Expected format is 'parameter/name = "
1328const void*
const kRegisterCplex ABSL_ATTRIBUTE_UNUSED = [] {
1336const void*
const kRegisterCplexMip ABSL_ATTRIBUTE_UNUSED = [] {
virtual MPSolver::BasisStatus row_status(int constraint_index) const
virtual void SetOptimizationDirection(bool maximize)
virtual MPSolver::BasisStatus column_status(int variable_index) const
virtual int64_t iterations() const
bool SetSolverSpecificParametersAsString(const std::string ¶meters) override
virtual double ComputeExactConditionNumber() const
virtual void SetVariableBounds(int var_index, double lb, double ub)
virtual void * underlying_solver()
virtual void ClearObjective()
virtual void AddRowConstraint(MPConstraint *const ct)
virtual void ClearConstraint(MPConstraint *const constraint)
virtual void ExtractNewVariables()
virtual void SetVariableInteger(int var_index, bool integer)
virtual MPSolver::ResultStatus Solve(MPSolverParameters const ¶m)
virtual void SetCoefficient(MPConstraint *const constraint, MPVariable const *const variable, double new_value, double old_value)
virtual std::string SolverVersion() const
virtual void SetPresolveMode(int value)
virtual int64_t nodes() const
virtual bool ReadParameterFile(std::string const &filename)
virtual void SetParameters(MPSolverParameters const ¶m)
virtual bool IsContinuous() const
virtual void SetObjectiveOffset(double value)
virtual void AddVariable(MPVariable *const var)
virtual void ExtractNewConstraints()
virtual bool IsLP() const
virtual void SetConstraintBounds(int row_index, double lb, double ub)
virtual void SetLpAlgorithm(int value)
virtual bool IsMIP() const
virtual void SetScalingMode(int value)
virtual void ExtractObjective()
virtual void SetObjectiveCoefficient(MPVariable const *const variable, double coefficient)
virtual void SetDualTolerance(double value)
CplexInterface(MPSolver *const solver, bool mip)
virtual std::string ValidFileExtensionForParameterFile() const
virtual void SetRelativeMipGap(double value)
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_.
static MPSolverInterfaceFactoryRepository * GetInstance()
void Register(MPSolverInterfaceFactory factory, MPSolver::OptimizationProblemType problem_type, std::function< bool()> is_runtime_ready={})
void set_variable_as_extracted(int var_index, bool extracted)
bool CheckSolutionIsSynchronized() const
static constexpr int64_t kUnknownNumberOfIterations
friend class MPConstraint
void InvalidateSolutionSynchronization()
void set_constraint_as_extracted(int ct_index, bool extracted)
void ResetExtractionInformation()
virtual void SetIntegerParamToUnsupportedValue(MPSolverParameters::IntegerParam param, int value)
int last_constraint_index_
bool variable_is_extracted(int var_index) const
bool constraint_is_extracted(int ct_index) const
static constexpr int64_t kUnknownNumberOfNodes
double best_objective_bound_
void SetMIPParameters(const MPSolverParameters ¶m)
MPSolverInterface(MPSolver *solver)
void SetCommonParameters(const MPSolverParameters ¶m)
MPSolver::ResultStatus result_status_
SynchronizationStatus sync_status_
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.
@ CPLEX_LINEAR_PROGRAMMING
@ CPLEX_MIXED_INTEGER_PROGRAMMING
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)
ClosedInterval::Iterator begin(ClosedInterval interval)