16 #if defined(USE_XPRESS)
23 #include "absl/strings/str_format.h"
33 #define XPRS_INTEGER 'I'
34 #define XPRS_CONTINUOUS 'C'
35 #define STRINGIFY2(X) #X
36 #define STRINGIFY(X) STRINGIFY2(X)
38 void printError(
const XPRSprob& mLp,
int line) {
40 XPRSgetlasterror(mLp, errmsg);
41 VLOG(0) << absl::StrFormat(
"Function line %d did not execute correctly: %s\n",
46 int XPRSgetnumcols(
const XPRSprob& mLp) {
48 XPRSgetintattrib(mLp, XPRS_COLS, &nCols);
52 int XPRSgetnumrows(
const XPRSprob& mLp) {
54 XPRSgetintattrib(mLp, XPRS_ROWS, &nRows);
58 int XPRSgetitcnt(
const XPRSprob& mLp) {
60 XPRSgetintattrib(mLp, XPRS_SIMPLEXITER, &nIters);
64 int XPRSgetnodecnt(
const XPRSprob& mLp) {
66 XPRSgetintattrib(mLp, XPRS_NODES, &nNodes);
70 int XPRSsetobjoffset(
const XPRSprob& mLp,
double value) {
71 XPRSsetdblcontrol(mLp, XPRS_OBJRHS,
value);
75 enum XPRS_BASIS_STATUS {
85 #define XPRS_NAN std::numeric_limits<double>::quiet_NaN()
91 #define CHECK_STATUS(s) \
93 int const status_ = s; \
94 CHECK_EQ(0, status_); \
99 using std::unique_ptr;
106 class XpressInterface :
public MPSolverInterface {
111 explicit XpressInterface(MPSolver*
const solver,
bool mip);
115 virtual void SetOptimizationDirection(
bool maximize);
123 virtual void Reset();
125 virtual void SetVariableBounds(
int var_index,
double lb,
double ub);
126 virtual void SetVariableInteger(
int var_index,
bool integer);
127 virtual void SetConstraintBounds(
int row_index,
double lb,
double ub);
129 virtual void AddRowConstraint(MPConstraint*
const ct);
130 virtual void AddVariable(MPVariable*
const var);
131 virtual void SetCoefficient(MPConstraint*
const constraint,
132 MPVariable
const*
const variable,
133 double new_value,
double old_value);
136 virtual void ClearConstraint(MPConstraint*
const constraint);
138 virtual void SetObjectiveCoefficient(MPVariable
const*
const variable,
141 virtual void SetObjectiveOffset(
double value);
143 virtual void ClearObjective();
147 virtual int64 iterations()
const;
149 virtual int64 nodes()
const;
161 virtual bool IsContinuous()
const {
return IsLP(); }
162 virtual bool IsLP()
const {
return !mMip; }
163 virtual bool IsMIP()
const {
return mMip; }
165 virtual void ExtractNewVariables();
166 virtual void ExtractNewConstraints();
167 virtual void ExtractObjective();
169 virtual std::string SolverVersion()
const;
171 virtual void* underlying_solver() {
return reinterpret_cast<void*
>(mLp); }
173 virtual double ComputeExactConditionNumber()
const {
174 if (!IsContinuous()) {
175 LOG(DFATAL) <<
"ComputeExactConditionNumber not implemented for"
176 <<
" XPRESS_MIXED_INTEGER_PROGRAMMING";
181 LOG(DFATAL) <<
"ComputeExactConditionNumber not implemented for"
182 <<
" XPRESS_LINEAR_PROGRAMMING";
188 virtual void SetParameters(MPSolverParameters
const& param);
190 virtual void SetRelativeMipGap(
double value);
191 virtual void SetPrimalTolerance(
double value);
192 virtual void SetDualTolerance(
double value);
193 virtual void SetPresolveMode(
int value);
194 virtual void SetScalingMode(
int value);
195 virtual void SetLpAlgorithm(
int value);
197 virtual bool ReadParameterFile(std::string
const& filename);
198 virtual std::string ValidFileExtensionForParameterFile()
const;
204 void InvalidateModelSynchronization() {
207 sync_status_ = MUST_RELOAD;
227 bool const supportIncrementalExtraction;
235 SlowSetCoefficient = 0x0001,
236 SlowClearConstraint = 0x0002,
237 SlowSetObjectiveCoefficient = 0x0004,
238 SlowClearObjective = 0x0008,
239 SlowSetConstraintBounds = 0x0010,
240 SlowSetVariableInteger = 0x0020,
241 SlowSetVariableBounds = 0x0040,
242 SlowUpdatesAll = 0xffff
248 unique_ptr<int[]>
mutable mCstat;
249 unique_ptr<int[]>
mutable mRstat;
252 static void MakeRhs(
double lb,
double ub,
double& rhs,
char& sense,
257 int init_xpress_env(
int xpress_oem_license_key = 0) {
260 const char* xpress_from_env = getenv(
"XPRESS");
261 std::string xpresspath;
263 if (xpress_from_env ==
nullptr) {
264 #if defined(XPRESS_PATH)
265 std::string path(STRINGIFY(XPRESS_PATH));
267 <<
"Environment variable XPRESS undefined. Trying compile path "
268 <<
"'" << path <<
"'";
269 #if defined(_MSC_VER)
271 path.erase(std::remove(path.begin(), path.end(),
'\"'), path.end());
272 xpresspath = path +
"\\bin";
274 xpresspath = path +
"/bin";
278 <<
"XpressInterface Error : Environment variable XPRESS undefined.\n";
282 xpresspath = xpress_from_env;
286 if (xpress_oem_license_key == 0) {
287 LOG(
WARNING) <<
"XpressInterface : Initialising xpress-MP with parameter "
288 << xpresspath << std::endl;
290 code = XPRSinit(xpresspath.c_str());
295 XPRSgetbanner(banner);
297 LOG(
WARNING) <<
"XpressInterface : Xpress banner :\n"
298 << banner << std::endl;
302 XPRSgetlicerrmsg(errmsg, 256);
304 VLOG(0) <<
"XpressInterface : License error : " << errmsg << std::endl;
305 VLOG(0) <<
"XpressInterface : XPRSinit returned code : " << code <<
"\n";
308 XPRSgetbanner(banner);
310 LOG(
ERROR) <<
"XpressInterface : Xpress banner :\n" << banner <<
"\n";
315 LOG(
WARNING) <<
"XpressInterface : Initialising xpress-MP with OEM key "
316 << xpress_oem_license_key <<
"\n";
320 char slicmsg[256] =
"";
323 XPRSlicense(&nvalue, slicmsg);
324 VLOG(0) <<
"XpressInterface : First message from XPRSLicense : " << slicmsg
327 nvalue = xpress_oem_license_key - ((nvalue * nvalue) / 19);
328 ierr = XPRSlicense(&nvalue, slicmsg);
330 VLOG(0) <<
"XpressInterface : Second message from XPRSLicense : " << slicmsg
333 VLOG(0) <<
"XpressInterface : Optimizer development software detected\n";
334 }
else if (ierr != 0) {
336 XPRSgetlicerrmsg(errmsg, 256);
338 LOG(
ERROR) <<
"XpressInterface : " << errmsg <<
"\n";
342 code = XPRSinit(NULL);
347 LOG(
ERROR) <<
"XPRSinit returned code : " << code <<
"\n";
354 XpressInterface::XpressInterface(MPSolver*
const solver,
bool mip)
355 : MPSolverInterface(solver),
358 supportIncrementalExtraction(false),
359 slowUpdates(static_cast<SlowUpdates>(SlowSetObjectiveCoefficient |
360 SlowClearObjective)),
363 int status = init_xpress_env();
364 CHECK_STATUS(status);
365 status = XPRScreateprob(&mLp);
366 CHECK_STATUS(status);
368 CHECK_STATUS(XPRSloadlp(mLp,
"newProb", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0));
371 XPRSchgobjsense(mLp,
maximize_ ? XPRS_OBJ_MAXIMIZE : XPRS_OBJ_MINIMIZE));
374 XpressInterface::~XpressInterface() {
375 CHECK_STATUS(XPRSdestroyprob(mLp));
379 std::string XpressInterface::SolverVersion()
const {
383 CHECK_STATUS(XPRSgetintcontrol(mLp, XPRS_VERSION, &version));
385 int const major = version / 1000000;
386 version -= major * 1000000;
387 int const release = version / 10000;
388 version -= release * 10000;
389 int const mod = version / 100;
390 version -= mod * 100;
391 int const fix = version;
393 return absl::StrFormat(
"XPRESS library version %d.%02d.%02d.%02d", major,
399 void XpressInterface::Reset() {
402 CHECK_STATUS(XPRSdestroyprob(mLp));
405 status = XPRScreateprob(&mLp);
406 CHECK_STATUS(status);
408 CHECK_STATUS(XPRSloadlp(mLp,
"newProb", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0));
411 XPRSchgobjsense(mLp,
maximize_ ? XPRS_OBJ_MAXIMIZE : XPRS_OBJ_MINIMIZE));
413 ResetExtractionInformation();
418 void XpressInterface::SetOptimizationDirection(
bool maximize) {
419 InvalidateSolutionSynchronization();
420 XPRSchgobjsense(mLp, maximize ? XPRS_OBJ_MAXIMIZE : XPRS_OBJ_MINIMIZE);
423 void XpressInterface::SetVariableBounds(
int var_index,
double lb,
double ub) {
424 InvalidateSolutionSynchronization();
432 if (!supportIncrementalExtraction && !(slowUpdates & SlowSetVariableBounds)) {
433 InvalidateModelSynchronization();
435 if (variable_is_extracted(var_index)) {
438 DCHECK_LT(var_index, last_variable_index_);
439 char const lu[2] = {
'L',
'U'};
440 double const bd[2] = {lb, ub};
441 int const idx[2] = {var_index, var_index};
442 CHECK_STATUS(XPRSchgbounds(mLp, 2, idx, lu, bd));
446 InvalidateModelSynchronization();
452 void XpressInterface::SetVariableInteger(
int var_index,
bool integer) {
453 InvalidateSolutionSynchronization();
465 if (!supportIncrementalExtraction && !slowUpdates &&
466 !SlowSetVariableInteger) {
467 InvalidateModelSynchronization();
470 if (variable_is_extracted(var_index)) {
474 DCHECK_LE(var_index, XPRSgetnumcols(mLp));
475 char const type = integer ? XPRS_INTEGER : XPRS_CONTINUOUS;
476 CHECK_STATUS(XPRSchgcoltype(mLp, 1, &var_index, &type));
478 InvalidateModelSynchronization();
482 <<
"Attempt to change variable to integer in non-MIP problem!";
488 void XpressInterface::MakeRhs(
double lb,
double ub,
double& rhs,
char& sense,
495 }
else if (lb > XPRS_MINUSINFINITY && ub < XPRS_PLUSINFINITY) {
515 }
else if (ub < XPRS_PLUSINFINITY || (std::abs(ub) == XPRS_PLUSINFINITY &&
516 std::abs(lb) > XPRS_PLUSINFINITY)) {
521 }
else if (lb > XPRS_MINUSINFINITY || (std::abs(lb) == XPRS_PLUSINFINITY &&
522 std::abs(ub) > XPRS_PLUSINFINITY)) {
536 DCHECK_GT(std::abs(lb), XPRS_PLUSINFINITY);
537 DCHECK_GT(std::abs(ub), XPRS_PLUSINFINITY);
538 if (std::abs(lb) > std::abs(ub)) {
539 rhs = (lb < 0) ? -XPRS_PLUSINFINITY : XPRS_PLUSINFINITY;
542 rhs = (ub < 0) ? -XPRS_PLUSINFINITY : XPRS_PLUSINFINITY;
549 void XpressInterface::SetConstraintBounds(
int index,
double lb,
double ub) {
550 InvalidateSolutionSynchronization();
558 if (!supportIncrementalExtraction &&
559 !(slowUpdates & SlowSetConstraintBounds)) {
560 InvalidateModelSynchronization();
562 if (constraint_is_extracted(
index)) {
568 MakeRhs(lb, ub, rhs, sense, range);
569 CHECK_STATUS(XPRSchgrhs(mLp, 1, &
index, &lb));
570 CHECK_STATUS(XPRSchgrowtype(mLp, 1, &
index, &sense));
571 CHECK_STATUS(XPRSchgrhsrange(mLp, 1, &
index, &range));
575 InvalidateModelSynchronization();
580 void XpressInterface::AddRowConstraint(MPConstraint*
const ct) {
587 InvalidateModelSynchronization();
590 void XpressInterface::AddVariable(MPVariable*
const ct) {
597 InvalidateModelSynchronization();
600 void XpressInterface::SetCoefficient(MPConstraint*
const constraint,
601 MPVariable
const*
const variable,
602 double new_value,
double) {
603 InvalidateSolutionSynchronization();
612 if (!supportIncrementalExtraction && !(slowUpdates & SlowSetCoefficient)) {
613 InvalidateModelSynchronization();
615 int const row = constraint->index();
616 int const col = variable->index();
617 if (constraint_is_extracted(
row) && variable_is_extracted(
col)) {
622 CHECK_STATUS(XPRSchgcoef(mLp,
row,
col, new_value));
626 InvalidateModelSynchronization();
631 void XpressInterface::ClearConstraint(MPConstraint*
const constraint) {
632 int const row = constraint->index();
633 if (!constraint_is_extracted(
row))
645 if (!(slowUpdates & SlowClearConstraint)) {
646 InvalidateModelSynchronization();
648 InvalidateSolutionSynchronization();
650 int const len = constraint->coefficients_.size();
651 unique_ptr<int[]> rowind(
new int[len]);
652 unique_ptr<int[]> colind(
new int[len]);
653 unique_ptr<double[]> val(
new double[len]);
655 const auto& coeffs = constraint->coefficients_;
656 for (
auto it(coeffs.begin()); it != coeffs.end(); ++it) {
657 int const col = it->first->index();
658 if (variable_is_extracted(
col)) {
666 CHECK_STATUS(XPRSchgmcoef(mLp, j, rowind.get(), colind.get(), val.get()));
670 void XpressInterface::SetObjectiveCoefficient(MPVariable
const*
const variable,
672 int const col = variable->index();
673 if (!variable_is_extracted(
col))
677 InvalidateSolutionSynchronization();
685 if (supportIncrementalExtraction ||
686 (slowUpdates & SlowSetObjectiveCoefficient)) {
689 InvalidateModelSynchronization();
693 void XpressInterface::SetObjectiveOffset(
double value) {
695 InvalidateSolutionSynchronization();
696 CHECK_STATUS(XPRSsetobjoffset(mLp,
value));
699 void XpressInterface::ClearObjective() {
700 InvalidateSolutionSynchronization();
707 if (supportIncrementalExtraction || (slowUpdates & SlowClearObjective)) {
708 int const cols = XPRSgetnumcols(mLp);
709 unique_ptr<int[]> ind(
new int[cols]);
710 unique_ptr<double[]> zero(
new double[cols]);
712 const auto& coeffs = solver_->objective_->coefficients_;
713 for (
auto it(coeffs.begin()); it != coeffs.end(); ++it) {
714 int const idx = it->first->index();
716 if (variable_is_extracted(idx)) {
723 if (j > 0) CHECK_STATUS(XPRSchgobj(mLp, j, ind.get(), zero.get()));
724 CHECK_STATUS(XPRSsetobjoffset(mLp, 0.0));
726 InvalidateModelSynchronization();
732 int64 XpressInterface::iterations()
const {
733 if (!CheckSolutionIsSynchronized())
return kUnknownNumberOfIterations;
734 return static_cast<int64>(XPRSgetitcnt(mLp));
737 int64 XpressInterface::nodes()
const {
739 if (!CheckSolutionIsSynchronized())
return kUnknownNumberOfNodes;
740 return static_cast<int64>(XPRSgetnodecnt(mLp));
742 LOG(DFATAL) <<
"Number of nodes only available for discrete problems";
743 return kUnknownNumberOfNodes;
748 MPSolver::BasisStatus XpressInterface::xformBasisStatus(
749 int xpress_basis_status) {
750 switch (xpress_basis_status) {
752 return MPSolver::AT_LOWER_BOUND;
754 return MPSolver::BASIC;
756 return MPSolver::AT_UPPER_BOUND;
757 case XPRS_FREE_SUPER:
758 return MPSolver::FREE;
760 LOG(DFATAL) <<
"Unknown XPRESS basis status";
761 return MPSolver::FREE;
766 MPSolver::BasisStatus XpressInterface::row_status(
int constraint_index)
const {
768 LOG(
FATAL) <<
"Basis status only available for continuous problems";
769 return MPSolver::FREE;
772 if (CheckSolutionIsSynchronized()) {
774 int const rows = XPRSgetnumrows(mLp);
775 unique_ptr<int[]> data(
new int[rows]);
777 CHECK_STATUS(XPRSgetbasis(mLp, 0, mRstat.get()));
784 return xformBasisStatus(mRstat[constraint_index]);
786 LOG(
FATAL) <<
"Row basis status not available";
787 return MPSolver::FREE;
792 MPSolver::BasisStatus XpressInterface::column_status(
int variable_index)
const {
794 LOG(
FATAL) <<
"Basis status only available for continuous problems";
795 return MPSolver::FREE;
798 if (CheckSolutionIsSynchronized()) {
800 int const cols = XPRSgetnumcols(mLp);
801 unique_ptr<int[]> data(
new int[cols]);
803 CHECK_STATUS(XPRSgetbasis(mLp, mCstat.get(), 0));
810 return xformBasisStatus(mCstat[variable_index]);
812 LOG(
FATAL) <<
"Column basis status not available";
813 return MPSolver::FREE;
818 void XpressInterface::ExtractNewVariables() {
822 InvalidateSolutionSynchronization();
824 if (!supportIncrementalExtraction) {
827 CHECK(last_variable_index_ == 0 ||
828 last_variable_index_ == solver_->variables_.size());
829 CHECK(last_constraint_index_ == 0 ||
830 last_constraint_index_ == solver_->constraints_.size());
833 int const last_extracted = last_variable_index_;
834 int const var_count = solver_->variables_.size();
835 int newcols = var_count - last_extracted;
839 unique_ptr<double[]> obj(
new double[newcols]);
840 unique_ptr<double[]> lb(
new double[newcols]);
841 unique_ptr<double[]> ub(
new double[newcols]);
842 unique_ptr<char[]> ctype(
new char[newcols]);
843 unique_ptr<const char*[]> colname(
new const char*[newcols]);
845 bool have_names =
false;
846 for (
int j = 0, varidx = last_extracted; j < newcols; ++j, ++varidx) {
847 MPVariable
const*
const var = solver_->variables_[varidx];
850 ctype[j] =
var->integer() ? XPRS_INTEGER : XPRS_CONTINUOUS;
851 colname[j] =
var->name().empty() ? 0 :
var->name().c_str();
852 have_names = have_names ||
var->name().empty();
853 obj[j] = solver_->objective_->GetCoefficient(
var);
861 std::vector<MPVariable*>
const& variables = solver_->variables();
862 for (
int j = last_extracted; j < var_count; ++j) {
863 CHECK(!variable_is_extracted(variables[j]->
index()));
864 set_variable_as_extracted(variables[j]->
index(),
true);
868 bool use_newcols =
true;
870 if (supportIncrementalExtraction) {
879 unique_ptr<int[]> collen(
new int[newcols]);
880 for (
int j = 0; j < newcols; ++j) collen[j] = 0;
884 for (
int i = 0; i < last_constraint_index_; ++i) {
885 MPConstraint
const*
const ct = solver_->constraints_[i];
886 CHECK(constraint_is_extracted(
ct->index()));
887 const auto& coeffs =
ct->coefficients_;
888 for (
auto it(coeffs.begin()); it != coeffs.end(); ++it) {
889 int const idx = it->first->index();
890 if (variable_is_extracted(idx) && idx > last_variable_index_) {
891 collen[idx - last_variable_index_]++;
902 unique_ptr<int[]> begin(
new int[newcols + 2]);
903 unique_ptr<int[]> cmatind(
new int[nonzeros]);
904 unique_ptr<double[]> cmatval(
new double[nonzeros]);
915 int* cmatbeg = begin.get();
919 for (
int j = 0; j < newcols; ++j)
920 cmatbeg[j + 1] = cmatbeg[j] + collen[j];
922 for (
int i = 0; i < last_constraint_index_; ++i) {
923 MPConstraint
const*
const ct = solver_->constraints_[i];
924 int const row =
ct->index();
925 const auto& coeffs =
ct->coefficients_;
926 for (
auto it(coeffs.begin()); it != coeffs.end(); ++it) {
927 int const idx = it->first->index();
928 if (variable_is_extracted(idx) && idx > last_variable_index_) {
929 int const nz = cmatbeg[idx]++;
931 cmatval[nz] = it->second;
936 CHECK_STATUS(XPRSaddcols(mLp, newcols, nonzeros, obj.get(), cmatbeg,
937 cmatind.get(), cmatval.get(), lb.get(),
946 std::vector<int> collen(newcols, 0);
947 std::vector<int> cmatbeg(newcols, 0);
948 unique_ptr<int[]> cmatind(
new int[1]);
949 unique_ptr<double[]> cmatval(
new double[1]);
953 CHECK_STATUS(XPRSaddcols(mLp, newcols, 0, obj.get(), cmatbeg.data(),
954 cmatind.get(), cmatval.get(), lb.get(),
956 int const cols = XPRSgetnumcols(mLp);
957 unique_ptr<int[]> ind(
new int[newcols]);
958 for (
int j = 0; j < cols; ++j) ind[j] = j;
960 XPRSchgcoltype(mLp, cols - last_extracted, ind.get(), ctype.get()));
965 if (mMip && XPRSgetnumcols(mLp) > 0) {
968 int const cols = XPRSgetnumcols(mLp);
969 unique_ptr<int[]> ind(
new int[newcols]);
970 for (
int j = last_extracted; j < cols; ++j)
971 ind[j - last_extracted] = j;
972 CHECK_STATUS(XPRSchgcoltype(mLp, cols - last_extracted, ind.get(),
978 int const cols = XPRSgetnumcols(mLp);
979 if (cols > last_extracted) {
980 std::vector<int> colsToDelete;
981 for (
int i = last_extracted; i < cols; ++i) colsToDelete.push_back(i);
982 (void)XPRSdelcols(mLp, colsToDelete.size(), colsToDelete.data());
984 std::vector<MPVariable*>
const& variables = solver_->variables();
985 int const size = variables.size();
986 for (
int j = last_extracted; j < size; ++j)
987 set_variable_as_extracted(j,
false);
994 void XpressInterface::ExtractNewConstraints() {
997 if (!supportIncrementalExtraction) {
1000 CHECK(last_variable_index_ == 0 ||
1001 last_variable_index_ == solver_->variables_.size());
1002 CHECK(last_constraint_index_ == 0 ||
1003 last_constraint_index_ == solver_->constraints_.size());
1006 int const offset = last_constraint_index_;
1007 int const total = solver_->constraints_.size();
1009 if (total > offset) {
1012 InvalidateSolutionSynchronization();
1014 int newCons = total - offset;
1015 int const cols = XPRSgetnumcols(mLp);
1017 int const chunk = newCons;
1021 for (
int c = offset; c < total; ++c) set_constraint_as_extracted(c,
true);
1024 unique_ptr<int[]> rmatind(
new int[cols]);
1025 unique_ptr<double[]> rmatval(
new double[cols]);
1026 unique_ptr<int[]> rmatbeg(
new int[chunk]);
1027 unique_ptr<char[]> sense(
new char[chunk]);
1028 unique_ptr<double[]> rhs(
new double[chunk]);
1029 unique_ptr<char const*[]>
name(
new char const*[chunk]);
1030 unique_ptr<double[]> rngval(
new double[chunk]);
1031 unique_ptr<int[]> rngind(
new int[chunk]);
1032 bool haveRanges =
false;
1037 for (
int c = 0; c < newCons; ) {
1041 for (; c < newCons && nextRow < chunk; ++c, ++nextRow) {
1042 MPConstraint
const*
const ct = solver_->constraints_[offset + c];
1046 if (nextNz +
ct->coefficients_.size() > cols) {
1052 MakeRhs(
ct->lb(),
ct->ub(), rhs[nextRow], sense[nextRow],
1054 haveRanges = haveRanges || (rngval[nextRow] != 0.0);
1055 rngind[nextRow] = offset + c;
1058 rmatbeg[nextRow] = nextNz;
1059 const auto& coeffs =
ct->coefficients_;
1060 for (
auto it(coeffs.begin()); it != coeffs.end(); ++it) {
1061 int const idx = it->first->index();
1062 if (variable_is_extracted(idx)) {
1065 rmatind[nextNz] = idx;
1066 rmatval[nextNz] = it->second;
1072 name[nextRow] =
ct->name().empty() ? 0 :
ct->name().c_str();
1075 CHECK_STATUS(XPRSaddrows(mLp, nextRow, nextNz, sense.get(), rhs.get(),
1076 rngval.get(), rmatbeg.get(), rmatind.get(),
1080 XPRSchgrhsrange(mLp, nextRow, rngind.get(), rngval.get()));
1086 int const rows = XPRSgetnumrows(mLp);
1087 std::vector<int> rowsToDelete;
1088 for (
int i = offset; i < rows; ++i) rowsToDelete.push_back(i);
1090 (void)XPRSdelrows(mLp, rowsToDelete.size(), rowsToDelete.data());
1091 std::vector<MPConstraint*>
const& constraints = solver_->constraints();
1092 int const size = constraints.size();
1093 for (
int i = offset; i < size; ++i) set_constraint_as_extracted(i,
false);
1100 void XpressInterface::ExtractObjective() {
1104 int const cols = XPRSgetnumcols(mLp);
1107 unique_ptr<int[]> ind(
new int[cols]);
1108 unique_ptr<double[]> val(
new double[cols]);
1109 for (
int j = 0; j < cols; ++j) {
1114 const auto& coeffs = solver_->objective_->coefficients_;
1115 for (
auto it = coeffs.begin(); it != coeffs.end(); ++it) {
1116 int const idx = it->first->index();
1117 if (variable_is_extracted(idx)) {
1119 val[idx] = it->second;
1123 CHECK_STATUS(XPRSchgobj(mLp, cols, ind.get(), val.get()));
1124 CHECK_STATUS(XPRSsetobjoffset(mLp, solver_->Objective().offset()));
1129 void XpressInterface::SetParameters(
const MPSolverParameters& param) {
1130 SetCommonParameters(param);
1131 if (mMip) SetMIPParameters(param);
1134 void XpressInterface::SetRelativeMipGap(
double value) {
1136 CHECK_STATUS(XPRSsetdblcontrol(mLp, XPRS_MIPRELSTOP,
value));
1138 LOG(
WARNING) <<
"The relative MIP gap is only available "
1139 <<
"for discrete problems.";
1143 void XpressInterface::SetPrimalTolerance(
double value) {
1144 CHECK_STATUS(XPRSsetdblcontrol(mLp, XPRS_FEASTOL,
value));
1147 void XpressInterface::SetDualTolerance(
double value) {
1148 CHECK_STATUS(XPRSsetdblcontrol(mLp, XPRS_OPTIMALITYTOL,
value));
1151 void XpressInterface::SetPresolveMode(
int value) {
1152 MPSolverParameters::PresolveValues
const presolve =
1153 static_cast<MPSolverParameters::PresolveValues
>(
value);
1156 case MPSolverParameters::PRESOLVE_OFF:
1157 CHECK_STATUS(XPRSsetintcontrol(mLp, XPRS_PRESOLVE, 0));
1159 case MPSolverParameters::PRESOLVE_ON:
1160 CHECK_STATUS(XPRSsetintcontrol(mLp, XPRS_PRESOLVE, 1));
1163 SetIntegerParamToUnsupportedValue(MPSolverParameters::PRESOLVE,
value);
1167 void XpressInterface::SetScalingMode(
int value) {
1168 MPSolverParameters::ScalingValues
const scaling =
1169 static_cast<MPSolverParameters::ScalingValues
>(
value);
1172 case MPSolverParameters::SCALING_OFF:
1173 CHECK_STATUS(XPRSsetintcontrol(mLp, XPRS_SCALING, 0));
1175 case MPSolverParameters::SCALING_ON:
1176 CHECK_STATUS(XPRSsetdefaultcontrol(mLp, XPRS_SCALING));
1187 void XpressInterface::SetLpAlgorithm(
int value) {
1188 MPSolverParameters::LpAlgorithmValues
const algorithm =
1189 static_cast<MPSolverParameters::LpAlgorithmValues
>(
value);
1193 switch (algorithm) {
1194 case MPSolverParameters::DUAL:
1197 case MPSolverParameters::PRIMAL:
1200 case MPSolverParameters::BARRIER:
1205 if (alg == XPRS_DEFAULTALG) {
1206 SetIntegerParamToUnsupportedValue(MPSolverParameters::LP_ALGORITHM,
value);
1208 CHECK_STATUS(XPRSsetintcontrol(mLp, XPRS_DEFAULTALG, alg));
1212 bool XpressInterface::ReadParameterFile(std::string
const& filename) {
1214 LOG(DFATAL) <<
"ReadParameterFile not implemented for XPRESS interface";
1218 std::string XpressInterface::ValidFileExtensionForParameterFile()
const {
1233 MPSolverParameters::IncrementalityValues
const inc =
1234 static_cast<MPSolverParameters::IncrementalityValues
>(
1235 param.GetIntegerParam(MPSolverParameters::INCREMENTALITY));
1237 case MPSolverParameters::INCREMENTALITY_OFF: {
1242 case MPSolverParameters::INCREMENTALITY_ON: {
1243 XPRSsetintcontrol(mLp, XPRS_CRASH, 0);
1253 if (!supportIncrementalExtraction && sync_status_ == MUST_RELOAD) Reset();
1255 VLOG(1) << absl::StrFormat(
"Model build in %.3f seconds.", timer.
Get());
1258 XPRSsetintcontrol(mLp, XPRS_OUTPUTLOG, quiet() ? 0 : 1);
1264 solver_->SetSolverSpecificParametersAsString(
1265 solver_->solver_specific_parameter_string_);
1266 SetParameters(param);
1267 if (solver_->time_limit()) {
1268 VLOG(1) <<
"Setting time limit = " << solver_->time_limit() <<
" ms.";
1271 CHECK_STATUS(XPRSsetdblcontrol(mLp, XPRS_MAXTIME,
1272 -1.0 * solver_->time_limit_in_secs()));
1283 status = XPRSmaxim(mLp,
"g");
1285 status = XPRSminim(mLp,
"g");
1286 XPRSgetintattrib(mLp, XPRS_MIPSTATUS, &xpressstat);
1289 status = XPRSmaxim(mLp,
"");
1291 status = XPRSminim(mLp,
"");
1292 XPRSgetintattrib(mLp, XPRS_LPSTATUS, &xpressstat);
1296 XPRSsetintcontrol(mLp, XPRS_OUTPUTLOG, 0);
1299 VLOG(1) << absl::StrFormat(
"Failed to optimize MIP. Error %d", status);
1303 VLOG(1) << absl::StrFormat(
"Solved in %.3f seconds.", timer.
Get());
1306 VLOG(1) << absl::StrFormat(
"XPRESS solution status %d.", xpressstat);
1309 bool const feasible = (mMip && (xpressstat == XPRS_MIP_OPTIMAL ||
1310 xpressstat == XPRS_MIP_SOLUTION)) ||
1311 (!mMip && xpressstat == XPRS_LP_OPTIMAL);
1314 int const rows = XPRSgetnumrows(mLp);
1315 int const cols = XPRSgetnumcols(mLp);
1316 DCHECK_EQ(rows, solver_->constraints_.size());
1317 DCHECK_EQ(cols, solver_->variables_.size());
1320 objective_value_ = XPRS_NAN;
1321 best_objective_bound_ = XPRS_NAN;
1324 CHECK_STATUS(XPRSgetdblattrib(mLp, XPRS_MIPOBJVAL, &objective_value_));
1325 CHECK_STATUS(XPRSgetdblattrib(mLp, XPRS_BESTBOUND, &best_objective_bound_));
1327 CHECK_STATUS(XPRSgetdblattrib(mLp, XPRS_LPOBJVAL, &objective_value_));
1330 VLOG(1) <<
"objective=" << objective_value_
1331 <<
", bound=" << best_objective_bound_;
1338 unique_ptr<double[]> x(
new double[cols]);
1339 CHECK_STATUS(XPRSgetmipsol(mLp, x.get(), 0));
1340 for (
int i = 0; i < solver_->variables_.size(); ++i) {
1341 MPVariable*
const var = solver_->variables_[i];
1342 var->set_solution_value(x[i]);
1343 VLOG(3) <<
var->name() <<
": value =" << x[i];
1347 for (
int i = 0; i < solver_->variables_.size(); ++i)
1348 solver_->variables_[i]->set_solution_value(XPRS_NAN);
1352 for (
int i = 0; i < solver_->variables_.size(); ++i)
1353 solver_->variables_[i]->set_reduced_cost(XPRS_NAN);
1354 for (
int i = 0; i < solver_->constraints_.size(); ++i)
1355 solver_->constraints_[i]->set_dual_value(XPRS_NAN);
1359 unique_ptr<double[]> x(
new double[cols]);
1360 unique_ptr<double[]> dj(
new double[cols]);
1361 if (feasible) CHECK_STATUS(XPRSgetlpsol(mLp, x.get(), 0, 0, dj.get()));
1362 for (
int i = 0; i < solver_->variables_.size(); ++i) {
1363 MPVariable*
const var = solver_->variables_[i];
1364 var->set_solution_value(x[i]);
1365 bool value =
false, dual =
false;
1368 var->set_solution_value(x[i]);
1371 var->set_solution_value(XPRS_NAN);
1374 var->set_reduced_cost(dj[i]);
1377 var->set_reduced_cost(XPRS_NAN);
1380 << (
value ? absl::StrFormat(
" value = %f", x[i]) :
"")
1381 << (dual ?
absl::StrFormat(
" reduced cost = %f", dj[i]) :
"");
1386 unique_ptr<double[]> pi(
new double[rows]);
1388 CHECK_STATUS(XPRSgetlpsol(mLp, 0, 0, pi.get(), 0));
1390 for (
int i = 0; i < solver_->constraints_.size(); ++i) {
1391 MPConstraint*
const ct = solver_->constraints_[i];
1394 ct->set_dual_value(pi[i]);
1397 ct->set_dual_value(XPRS_NAN);
1399 VLOG(4) <<
"row " <<
ct->index() <<
":"
1400 << (dual ? absl::StrFormat(
" dual = %f", pi[i]) :
"");
1407 switch (xpressstat) {
1408 case XPRS_MIP_OPTIMAL:
1409 result_status_ = MPSolver::OPTIMAL;
1411 case XPRS_MIP_INFEAS:
1412 result_status_ = MPSolver::INFEASIBLE;
1414 case XPRS_MIP_UNBOUNDED:
1415 result_status_ = MPSolver::UNBOUNDED;
1418 result_status_ = feasible ? MPSolver::FEASIBLE : MPSolver::ABNORMAL;
1422 switch (xpressstat) {
1423 case XPRS_LP_OPTIMAL:
1424 result_status_ = MPSolver::OPTIMAL;
1426 case XPRS_LP_INFEAS:
1427 result_status_ = MPSolver::INFEASIBLE;
1429 case XPRS_LP_UNBOUNDED:
1430 result_status_ = MPSolver::UNBOUNDED;
1433 result_status_ = feasible ? MPSolver::FEASIBLE : MPSolver::ABNORMAL;
1438 sync_status_ = SOLUTION_SYNCHRONIZED;
1439 return result_status_;
1442 MPSolverInterface* BuildXpressInterface(
bool mip, MPSolver*
const solver) {
1443 return new XpressInterface(solver, mip);
#define DCHECK_LE(val1, val2)
#define DCHECK_GT(val1, val2)
#define DCHECK_LT(val1, val2)
#define DCHECK(condition)
#define DCHECK_EQ(val1, val2)
#define VLOG(verboselevel)
ResultStatus
The status of solving the problem.
BasisStatus
Advanced usage: possible basis status values for a variable and the slack variable of a linear constr...
A C++ wrapper that provides a simple and unified interface to several linear programming and mixed in...
void ShutdownGoogleLogging()
CpSolverResponse Solve(const CpModelProto &model_proto)
Solves the given CpModelProto and returns an instance of CpSolverResponse.
The vehicle routing library lets one model and solve generic vehicle routing problems ranging from th...