23#include "absl/log/check.h"
24#include "absl/log/die_if_null.h"
25#include "absl/memory/memory.h"
26#include "absl/status/status.h"
27#include "absl/status/statusor.h"
28#include "absl/strings/string_view.h"
29#include "absl/types/span.h"
38bool checkInt32Overflow(
const std::size_t value) {
return value >
INT32_MAX; }
43absl::Status Xpress::ToStatus(
const int xprs_err,
44 const absl::StatusCode code)
const {
46 return absl::OkStatus();
52 <<
"Xpress error code: " << xprs_err <<
", message: " << errmsg;
55 <<
" (message could not be fetched)";
59 initIntControlDefaults();
62absl::StatusOr<std::unique_ptr<Xpress>>
Xpress::New(absl::string_view) {
64 CHECK(correctlyLoaded);
68 return absl::WrapUnique(
new Xpress(model));
72 std::string truncated(name);
74 if (truncated.length() > maxLength.value_or(INT_MAX)) {
75 truncated = truncated.substr(0, maxLength.value_or(INT_MAX));
92void Xpress::initIntControlDefaults() {
94 for (
auto control : controls) {
95 int_control_defaults_[control] = GetIntControl(control).value();
100 const absl::Span<const double> lb,
101 const absl::Span<const double> ub,
102 const absl::Span<const char> vtype) {
103 return AddVars({}, {}, {}, obj, lb, ub, vtype);
107 const absl::Span<const int> vind,
108 const absl::Span<const double> vval,
109 const absl::Span<const double> obj,
110 const absl::Span<const double> lb,
111 const absl::Span<const double> ub,
112 const absl::Span<const char> vtype) {
113 if (checkInt32Overflow(lb.size())) {
114 return absl::InvalidArgumentError(
115 "XPRESS cannot handle more than 2^31 variables");
117 const int num_vars =
static_cast<int>(lb.size());
118 if (vind.size() != vval.size() || ub.size() != num_vars ||
119 vtype.size() != num_vars || (!obj.empty() && obj.size() != num_vars) ||
120 (!vbegin.empty() && vbegin.size() != num_vars)) {
121 return absl::InvalidArgumentError(
122 "Xpress::AddVars arguments are of inconsistent sizes");
124 double* c_obj =
nullptr;
126 c_obj =
const_cast<double*
>(obj.data());
129 return ToStatus(
XPRSaddcols(xpress_model_, num_vars, 0, c_obj,
nullptr,
130 nullptr,
nullptr, lb.data(), ub.data()));
134 const absl::Span<const double> rhs,
135 const absl::Span<const double> rng) {
136 const int num_cons =
static_cast<int>(sense.size());
137 if (rhs.size() != num_cons) {
138 return absl::InvalidArgumentError(
139 "RHS must have one element per constraint.");
141 return ToStatus(
XPRSaddrows(xpress_model_, num_cons, 0, sense.data(),
142 rhs.data(), rng.data(),
nullptr,
nullptr,
147 const absl::Span<const double> rhs,
148 const absl::Span<const double> rng,
149 const absl::Span<const int> start,
150 const absl::Span<const int> colind,
151 const absl::Span<const double> rowcoef) {
152 const int num_cons =
static_cast<int>(rowtype.size());
153 if (rhs.size() != num_cons) {
154 return absl::InvalidArgumentError(
155 "RHS must have one element per constraint.");
157 if (start.size() != num_cons) {
158 return absl::InvalidArgumentError(
159 "START must have one element per constraint.");
161 if (colind.size() != rowcoef.size()) {
162 return absl::InvalidArgumentError(
163 "COLIND and ROWCOEF must be of the same size.");
165 return ToStatus(
XPRSaddrows(xpress_model_, num_cons, 0, rowtype.data(),
166 rhs.data(), rng.data(), start.data(),
167 colind.data(), rowcoef.data()));
176 double constant,
const absl::Span<const int> col_index,
177 const absl::Span<const double> obj_coeffs) {
178 static int indexes[1] = {-1};
179 double xprs_values[1] = {-constant};
181 <<
"Failed to set objective offset in XPRESS";
183 const int n_cols =
static_cast<int>(col_index.size());
185 XPRSchgobj(xpress_model_, n_cols, col_index.data(), obj_coeffs.data()));
189 const absl::Span<const int> colind1,
const absl::Span<const int> colind2,
190 const absl::Span<const double> coefficients) {
191 const int ncoefs =
static_cast<int>(coefficients.size());
192 return ToStatus(
XPRSchgmqobj(xpress_model_, ncoefs, colind1.data(),
193 colind2.data(), coefficients.data()));
197 absl::Span<const int> colind,
198 absl::Span<const double> values) {
200 return ToStatus(
XPRSchgmcoef64(xpress_model_, n_coefs, rowind.data(),
201 colind.data(), values.data()));
209 absl::Span<double> duals,
210 absl::Span<double> reducedCosts) {
211 return ToStatus(
XPRSgetlpsol(xpress_model_, primals.data(),
nullptr,
212 duals.data(), reducedCosts.data()));
228 <<
"Error getting Xpress int control: " << control;
237 if (int_control_defaults_.count(control)) {
239 int_control_defaults_[control]));
241 return absl::InvalidArgumentError(
242 "Default value unknown for control " + std::to_string(control) +
243 ", consider adding it to Xpress::initIntControlDefaults");
249 <<
"Error getting Xpress int attribute: " << attribute;
256 <<
"Error getting Xpress double attribute: " << attribute;
278 <<
"Failed to retrieve dual status from XPRESS";
283 std::vector<int>& colBasis)
const {
287 XPRSgetbasis(xpress_model_, rowBasis.data(), colBasis.data()));
291 std::vector<int>& colBasis)
const {
292 if (rowBasis.size() != colBasis.size()) {
293 return absl::InvalidArgumentError(
294 "Row basis and column basis must be of same size.");
297 XPRSloadbasis(xpress_model_, rowBasis.data(), colBasis.data()));
302 std::vector<double> bounds;
303 bounds.reserve(nVars);
305 ToStatus(
XPRSgetlb(xpress_model_, bounds.data(), 0, nVars - 1)))
306 <<
"Failed to retrieve variable LB from XPRESS";
311 std::vector<double> bounds;
312 bounds.reserve(nVars);
314 ToStatus(
XPRSgetub(xpress_model_, bounds.data(), 0, nVars - 1)))
315 <<
"Failed to retrieve variable UB from XPRESS";
#define RETURN_IF_ERROR(expr)
absl::Status MipOptimize()
absl::Status ChgCoeffs(absl::Span< const int > rowind, absl::Span< const int > colind, absl::Span< const double > values)
int GetNumberOfConstraints() const
int GetNumberOfVariables() const
absl::StatusOr< std::vector< double > > GetVarUb() const
absl::Status SetIntControl(int control, int value)
absl::Status SetStartingBasis(std::vector< int > &rowBasis, std::vector< int > &colBasis) const
absl::StatusOr< int > GetDualStatus() const
absl::StatusOr< int > GetIntAttr(int attribute) const
absl::Status SetProbName(absl::string_view name)
absl::Status GetLpSol(absl::Span< double > primals, absl::Span< double > duals, absl::Span< double > reducedCosts)
absl::Status AddConstrs(absl::Span< const char > sense, absl::Span< const double > rhs, absl::Span< const double > rng)
absl::Status AddVars(absl::Span< const double > obj, absl::Span< const double > lb, absl::Span< const double > ub, absl::Span< const char > vtype)
absl::Status SetLinearObjective(double constant, absl::Span< const int > col_index, absl::Span< const double > obj_coeffs)
static absl::StatusOr< std::unique_ptr< Xpress > > New(absl::string_view model_name)
Creates a new Xpress.
absl::Status ResetIntControl(int control)
absl::Status LpOptimize(std::string flags)
absl::Status SetQuadraticObjective(absl::Span< const int > colind1, absl::Span< const int > colind2, absl::Span< const double > coefficients)
absl::StatusOr< int > GetIntControl(int control) const
absl::StatusOr< double > GetDoubleAttr(int attribute) const
static void XPRS_CC printXpressMessage(XPRSprob prob, void *data, const char *sMsg, int nLen, int nMsgLvl)
absl::Status GetBasis(std::vector< int > &rowBasis, std::vector< int > &colBasis) const
absl::Status SetObjectiveSense(bool maximize)
absl::StatusOr< std::vector< double > > GetVarLb() const
An object oriented wrapper for quadratic constraints in ModelStorage.
std::function< int(XPRSprob prob, int attrib, int *p_value)> XPRSgetintattrib
std::function< int(XPRSprob prob, int ncoefs, const int objqcol1[], const int objqcol2[], const double objqcoef[])> XPRSchgmqobj
std::function< int(XPRSprob prob, int attrib, double *p_value)> XPRSgetdblattrib
std::function< int(XPRSprob prob, void(XPRS_CC *f_message)(XPRSprob cbprob, void *cbdata, const char *msg, int msglen, int msgtype), void *p, int priority)> XPRSaddcbmessage
bool initXpressEnv(bool verbose, int xpress_oem_license_key)
! init XPRESS environment.
std::function< int(XPRSprob prob, const int rowstat[], const int colstat[])> XPRSloadbasis
std::function< int(XPRSprob prob, double lb[], int first, int last)> XPRSgetlb
std::function< int(XPRSprob prob, int control, int *p_value)> XPRSgetintcontrol
std::function< int(XPRSprob prob, double x[], double slack[], double duals[], double djs[])> XPRSgetlpsol
std::function< int(XPRSprob prob)> XPRSpostsolve
std::function< int(void)> XPRSfree
std::function< int(XPRSprob prob, int reason)> XPRSinterrupt
std::function< int(XPRSprob prob, int control, int value)> XPRSsetintcontrol
std::function< int(XPRSprob prob, int nrows, int ncoefs, const char rowtype[], const double rhs[], const double rng[], const int start[], const int colind[], const double rowcoef[])> XPRSaddrows
std::function< int(XPRSprob prob, char *errmsg)> XPRSgetlasterror
std::function< int(XPRSprob prob)> XPRSdestroyprob
std::function< int(XPRSprob prob, XPRSint64 ncoefs, const int rowind[], const int colind[], const double rowcoef[])> XPRSchgmcoef64
std::function< int(XPRSprob prob, double ub[], int first, int last)> XPRSgetub
std::function< int(XPRSprob prob, int ncols, int ncoefs, const double objcoef[], const int start[], const int rowind[], const double rowcoef[], const double lb[], const double ub[])> XPRSaddcols
std::function< int(XPRSprob prob, const char *flags)> XPRSmipoptimize
std::function< int(XPRSprob prob, int ncols, const int colind[], const double objcoef[])> XPRSchgobj
std::function< int(XPRSprob prob, int *status, double duals[], int first, int last)> XPRSgetduals
std::function< int(XPRSprob *p_prob)> XPRScreateprob
std::function< int(XPRSprob prob, const char *flags)> XPRSlpoptimize
std::function< int(XPRSprob prob, int objsense)> XPRSchgobjsense
std::function< int(XPRSprob prob, const char *probname)> XPRSsetprobname
std::function< int(XPRSprob prob, int rowstat[], int colstat[])> XPRSgetbasis
#define XPRS_OBJ_MAXIMIZE
struct xo_prob_struct * XPRSprob
Copyright 2019-2023 RTE.
#define XPRS_MAXPROBNAMELENGTH
#define XPRS_BARITERLIMIT
#define XPRS_CC
NOLINTEND(runtime/int)
#define XPRS_OBJ_MINIMIZE