From 9d8573a21a81191bf1fa4c72d893ddfea820736f Mon Sep 17 00:00:00 2001 From: Peter Mitri Date: Thu, 6 Nov 2025 09:46:41 +0100 Subject: [PATCH] [MPSolver] Add lazy constraints support in XPRESS interface] --- ortools/linear_solver/xpress_interface.cc | 11 +++++++++-- ortools/third_party_solvers/xpress_environment.cc | 2 ++ ortools/third_party_solvers/xpress_environment.h | 1 + 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/ortools/linear_solver/xpress_interface.cc b/ortools/linear_solver/xpress_interface.cc index c93f5e8caa..b10e4c78de 100644 --- a/ortools/linear_solver/xpress_interface.cc +++ b/ortools/linear_solver/xpress_interface.cc @@ -233,7 +233,7 @@ class XpressMPCallbackContext : public MPCallbackContext { }; void AddLazyConstraint(const LinearRange& lazy_constraint) override { LOG(WARNING) - << "AddLazyConstraint is not implemented yet in XPRESS interface"; + << "AddLazyConstraint inside Callback is not implemented yet in XPRESS interface"; }; double SuggestSolution( const absl::flat_hash_map& solution) override; @@ -1541,7 +1541,7 @@ void XpressInterface::ExtractNewConstraints() { unique_ptr sense(new char[chunk]); unique_ptr rhs(new double[chunk]); unique_ptr rngval(new double[chunk]); - + std::vector delayedRows; // Loop over the new constraints, collecting rows for up to // CHUNK constraints into the arrays so that adding constraints // is faster. @@ -1575,12 +1575,19 @@ void XpressInterface::ExtractNewConstraints() { ++nextNz; } } + if (ct->is_lazy()) { + delayedRows.push_back(offset + c); + } } if (nextRow > 0) { CHECK_STATUS(XPRSaddrows(mLp, nextRow, nextNz, sense.get(), rhs.get(), rngval.get(), rmatbeg.get(), rmatind.get(), rmatval.get())); } + if (!delayedRows.empty()) { + CHECK_STATUS(XPRSloaddelayedrows( + mLp, static_cast(delayedRows.size()), delayedRows.data())); + } } } catch (...) { // Undo all changes in case of error. diff --git a/ortools/third_party_solvers/xpress_environment.cc b/ortools/third_party_solvers/xpress_environment.cc index b41ca59b08..50cd6266dd 100644 --- a/ortools/third_party_solvers/xpress_environment.cc +++ b/ortools/third_party_solvers/xpress_environment.cc @@ -92,6 +92,7 @@ std::function XPRSgetro std::function XPRSgetcoltype = nullptr; std::function XPRSchgbounds = nullptr; std::function XPRSaddmipsol = nullptr; +std::function XPRSloaddelayedrows = nullptr; std::function XPRSgetlpsol = nullptr; std::function XPRSgetmipsol = nullptr; std::function XPRSchgobj = nullptr; @@ -167,6 +168,7 @@ void LoadXpressFunctions(DynamicLibrary* xpress_dynamic_library) { xpress_dynamic_library->GetFunction(&XPRSgetcoltype, "XPRSgetcoltype"); xpress_dynamic_library->GetFunction(&XPRSchgbounds, "XPRSchgbounds"); xpress_dynamic_library->GetFunction(&XPRSaddmipsol, "XPRSaddmipsol"); + xpress_dynamic_library->GetFunction(&XPRSloaddelayedrows, "XPRSloaddelayedrows"); xpress_dynamic_library->GetFunction(&XPRSgetlpsol, "XPRSgetlpsol"); xpress_dynamic_library->GetFunction(&XPRSgetmipsol, "XPRSgetmipsol"); xpress_dynamic_library->GetFunction(&XPRSchgobj, "XPRSchgobj"); diff --git a/ortools/third_party_solvers/xpress_environment.h b/ortools/third_party_solvers/xpress_environment.h index b8a7bd0a2a..f383c7f00d 100644 --- a/ortools/third_party_solvers/xpress_environment.h +++ b/ortools/third_party_solvers/xpress_environment.h @@ -525,6 +525,7 @@ OR_DLL extern std::function XPRSgetcoltype; extern std::function XPRSchgbounds; extern std::function XPRSaddmipsol; +extern std::function XPRSloaddelayedrows; extern std::function XPRSgetlpsol; extern std::function XPRSgetmipsol; extern std::function XPRSchgobj;