Google OR-Tools v9.15
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
g_xpress.cc
Go to the documentation of this file.
1// Copyright 2010-2025 Google LLC
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
15
16#include <climits>
17#include <cstddef>
18#include <cstdint>
19#include <memory>
20#include <string>
21#include <vector>
22
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"
34
36
37namespace {
38bool checkInt32Overflow(const std::size_t value) { return value > INT32_MAX; }
39template <typename T>
41T* forwardSpan(std::optional<absl::Span<T>> const& span) {
42 return span.has_value() ? span.value().data() : nullptr;
43}
44} // namespace
45
46constexpr int kXpressOk = 0;
47
48absl::Status Xpress::ToStatus(const int xprs_err,
49 const absl::StatusCode code) const {
50 if (xprs_err == kXpressOk) {
51 return absl::OkStatus();
52 }
53 char errmsg[512];
54 int status = XPRSgetlasterror(xpress_model_, errmsg);
55 if (status == kXpressOk) {
56 return util::StatusBuilder(code)
57 << "Xpress error code: " << xprs_err << ", message: " << errmsg;
58 }
59 return util::StatusBuilder(code) << "Xpress error code: " << xprs_err
60 << " (message could not be fetched)";
61}
62
63Xpress::Xpress(XPRSprob& model) : xpress_model_(ABSL_DIE_IF_NULL(model)) {
64 initIntControlDefaults();
65}
66
67absl::StatusOr<std::unique_ptr<Xpress>> Xpress::New(absl::string_view) {
68 bool correctlyLoaded = initXpressEnv();
69 CHECK(correctlyLoaded);
70 XPRSprob model;
71 CHECK_EQ(kXpressOk, XPRScreateprob(&model));
72 return absl::WrapUnique(new Xpress(model));
73}
74
75absl::Status Xpress::SetProbName(absl::string_view name) {
76 std::string truncated(name);
77 auto maxLength = GetIntAttr(XPRS_MAXPROBNAMELENGTH);
78 if (truncated.length() > maxLength.value_or(INT_MAX)) {
79 truncated = truncated.substr(0, maxLength.value_or(INT_MAX));
80 }
81 return ToStatus(XPRSsetprobname(xpress_model_, truncated.c_str()));
82}
83
84absl::Status Xpress::AddCbMessage(void(XPRS_CC* cb)(XPRSprob, void*,
85 char const*, int, int),
86 void* cbdata, int prio) {
87 return ToStatus(XPRSaddcbmessage(xpress_model_, cb, cbdata, prio));
88}
89
90absl::Status Xpress::RemoveCbMessage(void(XPRS_CC* cb)(XPRSprob, void*,
91 char const*, int, int),
92 void* cbdata) {
93 return ToStatus(XPRSremovecbmessage(xpress_model_, cb, cbdata));
94}
95
96absl::Status Xpress::AddCbChecktime(int(XPRS_CC* cb)(XPRSprob, void*),
97 void* cbdata, int prio) {
98 return ToStatus(XPRSaddcbchecktime(xpress_model_, cb, cbdata, prio));
99}
100
101absl::Status Xpress::RemoveCbChecktime(int(XPRS_CC* cb)(XPRSprob, void*),
102 void* cbdata) {
103 return ToStatus(XPRSremovecbchecktime(xpress_model_, cb, cbdata));
104}
105
107 CHECK_EQ(kXpressOk, XPRSdestroyprob(xpress_model_));
108 CHECK_EQ(kXpressOk, XPRSfree());
109}
110
111void Xpress::initIntControlDefaults() {
112 std::vector controls = {XPRS_LPITERLIMIT, XPRS_BARITERLIMIT};
113 for (auto control : controls) {
114 int_control_defaults_[control] = GetIntControl(control).value();
115 }
116}
117
118absl::Status Xpress::AddNames(int type, absl::Span<const char> names, int first,
119 int last) {
120 return ToStatus(XPRSaddnames(xpress_model_, type, names.data(), first, last));
121}
122
123// All span arguments can be missing to indicate "use default values".
124// Default objective value: 0
125// Default lower bound: 0
126// Default upper bound: infinity
127// Default type: continuous
128absl::Status Xpress::AddVars(std::size_t count,
129 const absl::Span<const double> obj,
130 const absl::Span<const double> lb,
131 const absl::Span<const double> ub,
132 const absl::Span<const char> vtype) {
133 ASSIGN_OR_RETURN(int const oldCols, GetIntAttr(XPRS_ORIGINALCOLS));
134 if (checkInt32Overflow(count) ||
135 checkInt32Overflow(std::size_t(oldCols) + std::size_t(count))) {
136 return absl::InvalidArgumentError(
137 "XPRESS cannot handle more than 2^31 variables");
138 }
139 const int num_vars = static_cast<int>(count);
140 double const* c_obj = nullptr;
141 if (!obj.empty()) {
142 if (obj.size() != count)
143 return absl::InvalidArgumentError(
144 "Xpress::AddVars objective argument has bad size");
145 c_obj = obj.data();
146 }
147 if (!lb.empty() && lb.size() != count)
148 return absl::InvalidArgumentError(
149 "Xpress::AddVars lower bound argument has bad size");
150 if (!ub.empty() && ub.size() != count)
151 return absl::InvalidArgumentError(
152 "Xpress::AddVars upper bound argument has bad size");
153 std::vector<int> colind;
154 if (!vtype.empty()) {
155 if (vtype.size() != count)
156 return absl::InvalidArgumentError(
157 "Xpress::AddVars type argument has bad size");
158 colind.reserve(count); // So that we don't OOM after adding
159 }
160 // XPRSaddcols64() allows to add variables with more than INT_MAX
161 // non-zero coefficients here. It does NOT allow adding more than INT_MAX
162 // variables.
163 // Since we don't add any non-zeros here, it is safe to use XPRSaddcols().
165 xpress_model_, num_vars, 0, c_obj, nullptr, nullptr, nullptr,
166 lb.size() ? lb.data() : nullptr, ub.size() ? ub.data() : nullptr)));
167 if (!vtype.empty()) {
168 for (int i = 0; i < num_vars; ++i) colind.push_back(oldCols + i);
169 int const ret =
170 XPRSchgcoltype(xpress_model_, num_vars, colind.data(), vtype.data());
171 if (ret != 0) {
172 // Changing the column type failed. We must roll back XPRSaddcols() and
173 // then return an error.
174 XPRSdelcols(xpress_model_, num_vars, colind.data());
175 }
176 return ToStatus(ret);
177 }
178 return absl::OkStatus();
179}
180
181absl::Status Xpress::AddConstrs(const absl::Span<const char> sense,
182 const absl::Span<const double> rhs,
183 const absl::Span<const double> rng) {
184 const int num_cons = static_cast<int>(sense.size());
185 if (rhs.size() != num_cons) {
186 return absl::InvalidArgumentError(
187 "RHS must have one element per constraint.");
188 }
189 return ToStatus(XPRSaddrows(xpress_model_, num_cons, 0, sense.data(),
190 rhs.data(), rng.data(), nullptr, nullptr,
191 nullptr));
192}
193
194absl::Status Xpress::AddConstrs(const absl::Span<const char> rowtype,
195 const absl::Span<const double> rhs,
196 const absl::Span<const double> rng,
197 const absl::Span<const int> start,
198 const absl::Span<const int> colind,
199 const absl::Span<const double> rowcoef) {
200 const int num_cons = static_cast<int>(rowtype.size());
201 if (rhs.size() != num_cons) {
202 return absl::InvalidArgumentError(
203 "RHS must have one element per constraint.");
204 }
205 if (start.size() != num_cons) {
206 return absl::InvalidArgumentError(
207 "START must have one element per constraint.");
208 }
209 if (colind.size() != rowcoef.size()) {
210 return absl::InvalidArgumentError(
211 "COLIND and ROWCOEF must be of the same size.");
212 }
213 return ToStatus(XPRSaddrows(xpress_model_, num_cons, 0, rowtype.data(),
214 rhs.data(), rng.data(), start.data(),
215 colind.data(), rowcoef.data()));
216}
217
218absl::Status Xpress::SetObjectiveSense(bool maximize) {
219 return ToStatus(XPRSchgobjsense(
220 xpress_model_, maximize ? XPRS_OBJ_MAXIMIZE : XPRS_OBJ_MINIMIZE));
221}
222
224 double constant, const absl::Span<const int> col_index,
225 const absl::Span<const double> obj_coeffs) {
226 static int indexes[1] = {-1};
227 double xprs_values[1] = {-constant};
228 RETURN_IF_ERROR(ToStatus(XPRSchgobj(xpress_model_, 1, indexes, xprs_values)))
229 << "Failed to set objective offset in XPRESS";
230
231 const int n_cols = static_cast<int>(col_index.size());
232 return ToStatus(
233 XPRSchgobj(xpress_model_, n_cols, col_index.data(), obj_coeffs.data()));
234}
235
237 const absl::Span<const int> colind1, const absl::Span<const int> colind2,
238 const absl::Span<const double> coefficients) {
239 const int ncoefs = static_cast<int>(coefficients.size());
240 return ToStatus(XPRSchgmqobj(xpress_model_, ncoefs, colind1.data(),
241 colind2.data(), coefficients.data()));
242}
243
244absl::Status Xpress::ChgCoeffs(absl::Span<const int> rowind,
245 absl::Span<const int> colind,
246 absl::Span<const double> values) {
247 const XPRSint64 n_coefs = static_cast<XPRSint64>(rowind.size());
248 return ToStatus(XPRSchgmcoef64(xpress_model_, n_coefs, rowind.data(),
249 colind.data(), values.data()));
250}
251
252absl::Status Xpress::LpOptimize(std::string flags) {
253 return ToStatus(XPRSlpoptimize(xpress_model_, flags.c_str()));
254}
255
256absl::Status Xpress::GetLpSol(absl::Span<double> primals,
257 absl::Span<double> duals,
258 absl::Span<double> reducedCosts) {
259 return ToStatus(XPRSgetlpsol(xpress_model_, primals.data(), nullptr,
260 duals.data(), reducedCosts.data()));
261}
262
263absl::Status Xpress::PostSolve() {
264 return ToStatus(XPRSpostsolve(xpress_model_));
265}
266
267absl::Status Xpress::Optimize(std::string const& flags, int* p_solvestatus,
268 int* p_solstatus) {
269 return ToStatus(
270 XPRSoptimize(xpress_model_, flags.c_str(), p_solvestatus, p_solstatus));
271}
272
274
275absl::Status Xpress::GetControlInfo(char const* name, int* p_id,
276 int* p_type) const {
277 return ToStatus(XPRSgetcontrolinfo(xpress_model_, name, p_id, p_type));
278}
279
280absl::StatusOr<int> Xpress::GetIntControl(int control) const {
281 int result;
282 RETURN_IF_ERROR(ToStatus(XPRSgetintcontrol(xpress_model_, control, &result)))
283 << "Error getting Xpress int control: " << control;
284 return result;
285}
286
287absl::Status Xpress::SetIntControl(int control, int value) {
288 return ToStatus(XPRSsetintcontrol(xpress_model_, control, value));
289}
290
291absl::Status Xpress::ResetIntControl(int control) {
292 if (int_control_defaults_.count(control)) {
293 return ToStatus(XPRSsetintcontrol(xpress_model_, control,
294 int_control_defaults_[control]));
295 }
296 return absl::InvalidArgumentError(
297 "Default value unknown for control " + std::to_string(control) +
298 ", consider adding it to Xpress::initIntControlDefaults");
299}
300
301absl::StatusOr<int64_t> Xpress::GetIntControl64(int control) const {
302 XPRSint64 result;
304 ToStatus(XPRSgetintcontrol64(xpress_model_, control, &result)))
305 << "Error getting Xpress int64 control: " << control;
306 return result;
307}
308
309absl::Status Xpress::SetIntControl64(int control, int64_t value) {
310 return ToStatus(XPRSsetintcontrol64(xpress_model_, control, value));
311}
312
313absl::StatusOr<double> Xpress::GetDblControl(int control) const {
314 double result;
315 RETURN_IF_ERROR(ToStatus(XPRSgetdblcontrol(xpress_model_, control, &result)))
316 << "Error getting Xpress double control: " << control;
317 return result;
318}
319
320absl::Status Xpress::SetDblControl(int control, double value) {
321 return ToStatus(XPRSsetdblcontrol(xpress_model_, control, value));
322}
323
324absl::StatusOr<std::string> Xpress::GetStrControl(int control) const {
325 int nbytes = 0;
327 ToStatus(XPRSgetstringcontrol(xpress_model_, control, NULL, 0, &nbytes)));
328 std::vector<char> result(nbytes,
329 '\0'); // nbytes CONTAINS the terminating nul!
331 xpress_model_, control, result.data(), nbytes, &nbytes)))
332 << "Error getting Xpress string control: " << control;
333 return std::string(result.data(), nbytes);
334}
335
336absl::Status Xpress::SetStrControl(int control, std::string const& value) {
337 return ToStatus(XPRSsetstrcontrol(xpress_model_, control, value.c_str()));
338}
339
340absl::StatusOr<int> Xpress::GetIntAttr(int attribute) const {
341 int result;
342 RETURN_IF_ERROR(ToStatus(XPRSgetintattrib(xpress_model_, attribute, &result)))
343 << "Error getting Xpress int attribute: " << attribute;
344 return result;
345}
346
347absl::StatusOr<double> Xpress::GetDoubleAttr(int attribute) const {
348 double result;
349 RETURN_IF_ERROR(ToStatus(XPRSgetdblattrib(xpress_model_, attribute, &result)))
350 << "Error getting Xpress double attribute: " << attribute;
351 return result;
352}
353
354absl::StatusOr<double> Xpress::GetObjectiveDoubleAttr(int objidx,
355 int attribute) const {
356 double result = 0.0;
358 ToStatus(XPRSgetobjdblattrib(xpress_model_, objidx, attribute, &result)))
359 << "Error getting Xpress objective double attribute: " << attribute;
360 return result;
361}
362
363absl::StatusOr<int> Xpress::GetDualStatus() const {
364 int status = 0;
365 double values[1];
366 // Even though we do not need the values, we have to fetch them, otherwise
367 // we'd get a segmentation fault
368 RETURN_IF_ERROR(ToStatus(XPRSgetduals(xpress_model_, &status, values, 0, 0)))
369 << "Failed to retrieve dual status from XPRESS";
370 return status;
371}
372
373absl::Status Xpress::GetBasis(std::vector<int>& rowBasis,
374 std::vector<int>& colBasis) const {
377 rowBasis.resize(rows);
378 colBasis.resize(cols);
379 return ToStatus(
380 XPRSgetbasis(xpress_model_, rowBasis.data(), colBasis.data()));
381}
382
383absl::Status Xpress::SetStartingBasis(std::vector<int>& rowBasis,
384 std::vector<int>& colBasis) const {
385 if (rowBasis.size() != colBasis.size()) {
386 return absl::InvalidArgumentError(
387 "Row basis and column basis must be of same size.");
388 }
389 return ToStatus(
390 XPRSloadbasis(xpress_model_, rowBasis.data(), colBasis.data()));
391}
392
393absl::StatusOr<std::vector<double>> Xpress::GetVarLb() const {
395 std::vector<double> bounds;
396 bounds.reserve(cols);
398 ToStatus(XPRSgetlb(xpress_model_, bounds.data(), 0, cols - 1)))
399 << "Failed to retrieve variable LB from XPRESS";
400 return bounds;
401}
402absl::StatusOr<std::vector<double>> Xpress::GetVarUb() const {
404 std::vector<double> bounds;
405 bounds.reserve(cols);
407 ToStatus(XPRSgetub(xpress_model_, bounds.data(), 0, cols - 1)))
408 << "Failed to retrieve variable UB from XPRESS";
409 return bounds;
410}
411
412absl::Status Xpress::Interrupt(int reason) {
413 return ToStatus(XPRSinterrupt(xpress_model_, reason));
414}
415
416absl::StatusOr<bool> Xpress::IsMIP() const {
418 if (ents != 0) return true;
420 if (sets != 0) return true;
421 return false;
422}
423
424absl::Status Xpress::GetDuals(int* p_status,
425 std::optional<absl::Span<double>> const& duals,
426 int first, int last) {
427 return ToStatus(
428 XPRSgetduals(xpress_model_, p_status, forwardSpan(duals), first, last));
429}
430absl::Status Xpress::GetSolution(int* p_status,
431 std::optional<absl::Span<double>> const& x,
432 int first, int last) {
433 return ToStatus(
434 XPRSgetsolution(xpress_model_, p_status, forwardSpan(x), first, last));
435}
436absl::Status Xpress::GetRedCosts(int* p_status,
437 std::optional<absl::Span<double>> const& dj,
438 int first, int last) {
439 return ToStatus(
440 XPRSgetredcosts(xpress_model_, p_status, forwardSpan(dj), first, last));
441}
442
446absl::Status Xpress::AddMIPSol(absl::Span<double const> vals,
447 absl::Span<int const> colind, char const* name) {
448 if (checkInt32Overflow(colind.size()))
449 return absl::InvalidArgumentError("more start values than columns");
450 if (colind.size() != vals.size())
451 return absl::InvalidArgumentError("inconsitent data to AddMIPSol()");
452 // XPRSaddmipsol() supports colind=nullptr, but we do not support that here
453 // since we don't need it.
454 return ToStatus(XPRSaddmipsol(xpress_model_, static_cast<int>(colind.size()),
455 vals.data(), colind.data(), name));
456}
457
458absl::Status Xpress::LoadDelayedRows(absl::Span<int const> rows) {
459 if (checkInt32Overflow(rows.size()))
460 return absl::InvalidArgumentError("more delayed rows than rows");
461 return ToStatus(XPRSloaddelayedrows(
462 xpress_model_, static_cast<int>(rows.size()), rows.data()));
463}
464
465absl::Status Xpress::LoadDirs(
466 absl::Span<int const> cols,
467 std::optional<absl::Span<int const>> const& prio,
468 std::optional<absl::Span<char const>> const& dir,
469 std::optional<absl::Span<double const>> const& up,
470 std::optional<absl::Span<double const>> const& down) {
471 if (checkInt32Overflow(cols.size()))
472 return absl::InvalidArgumentError("more directions than columns");
473 return ToStatus(XPRSloaddirs(xpress_model_, static_cast<int>(cols.size()),
474 cols.data(), forwardSpan(prio), forwardSpan(dir),
475 forwardSpan(up), forwardSpan(down)));
476}
477
478absl::Status Xpress::SetObjectiveIntControl(int obj, int control, int value) {
479 return ToStatus(XPRSsetobjintcontrol(xpress_model_, obj, control, value));
480}
481absl::Status Xpress::SetObjectiveDoubleControl(int obj, int control,
482 double value) {
483 return ToStatus(XPRSsetobjdblcontrol(xpress_model_, obj, control, value));
484}
485absl::StatusOr<int> Xpress::AddObjective(double constant, int ncols,
486 absl::Span<int const> colind,
487 absl::Span<double const> objcoef,
488 int priority, double weight) {
490 if (objs == INT_MAX) {
491 return util::StatusBuilder(absl::StatusCode::kInvalidArgument)
492 << "too many objectives";
493 }
494 int ret = XPRSaddobj(xpress_model_, ncols, colind.data(), objcoef.data(),
495 priority, weight);
496 if (ret) {
497 return ToStatus(ret);
498 }
499 if (constant != 0.0) {
500 ret =
501 XPRSsetobjdblcontrol(xpress_model_, objs, XPRS_OBJECTIVE_RHS, constant);
502 if (ret) {
503 XPRSdelobj(xpress_model_, objs);
504 return ToStatus(ret);
505 }
506 }
507 return objs;
508}
509
510absl::StatusOr<double> Xpress::CalculateObjectiveN(int objidx,
511 double const* solution) {
512 double objval = 0.0;
513 int ret = XPRScalcobjn(xpress_model_, objidx, solution, &objval);
514 if (ret) {
515 return ToStatus(ret);
516 }
517 return objval;
518}
519
520absl::Status Xpress::AddSets(absl::Span<char const> settype,
521 absl::Span<XPRSint64 const> start,
522 absl::Span<int const> colind,
523 absl::Span<double const> refval) {
524 ASSIGN_OR_RETURN(int const oldSets, GetIntAttr(XPRS_ORIGINALSETS));
525 if (checkInt32Overflow(settype.size()) ||
526 checkInt32Overflow(std::size_t(oldSets) + settype.size())) {
527 return absl::InvalidArgumentError(
528 "XPRESS cannot handle more than 2^31 SOSs");
529 }
530 return ToStatus(XPRSaddsets64(xpress_model_, static_cast<int>(settype.size()),
531 colind.size(), settype.data(), start.data(),
532 colind.data(), refval.data()));
533}
534
535absl::Status Xpress::SetIndicators(absl::Span<int const> rowind,
536 absl::Span<int const> colind,
537 absl::Span<int const> complement) {
539 if (checkInt32Overflow(rowind.size()) ||
540 checkInt32Overflow(std::size_t(oldInds) + rowind.size())) {
541 return absl::InvalidArgumentError(
542 "XPRESS cannot handle more than 2^31 indicators");
543 }
544 if (rowind.size() != colind.size() || rowind.size() != complement.size()) {
545 return absl::InvalidArgumentError(
546 "inconsistent arguments to SetInidicators");
547 }
548 return ToStatus(
549 XPRSsetindicators(xpress_model_, static_cast<int>(rowind.size()),
550 rowind.data(), colind.data(), complement.data()));
551}
552
553absl::Status Xpress::AddRows(absl::Span<char const> rowtype,
554 absl::Span<double const> rhs,
555 absl::Span<double const> rng,
556 absl::Span<XPRSint64 const> start,
557 absl::Span<int const> colind,
558 absl::Span<double const> rowcoef) {
559 ASSIGN_OR_RETURN(int const oldRows, GetIntAttr(XPRS_ORIGINALROWS));
560 if (checkInt32Overflow(rowtype.size()) ||
561 checkInt32Overflow(std::size_t(oldRows) + rowtype.size())) {
562 return absl::InvalidArgumentError(
563 "XPRESS cannot handle more than 2^31 rows");
564 }
565 if (rowtype.size() != rhs.size() || rowtype.size() != rng.size() ||
566 rowtype.size() != start.size() || colind.size() != rowcoef.size())
567 return absl::InvalidArgumentError("inconsistent arguments to AddRows");
568 return ToStatus(XPRSaddrows64(xpress_model_, static_cast<int>(rowtype.size()),
569 colind.size(), rowtype.data(), rhs.data(),
570 rng.data(), start.data(), colind.data(),
571 rowcoef.data()));
572}
573
574absl::Status Xpress::AddQRow(char sense, double rhs, double rng,
575 absl::Span<int const> colind,
576 absl::Span<double const> rowcoef,
577 absl::Span<int const> qcol1,
578 absl::Span<int const> qcol2,
579 absl::Span<double const> qcoef) {
580 ASSIGN_OR_RETURN(int const oldRows, GetIntAttr(XPRS_ORIGINALROWS));
581 if (checkInt32Overflow(std::size_t(oldRows) + 1))
582 return absl::InvalidArgumentError(
583 "XPRESS cannot handle more than 2^31 rows");
584 XPRSint64 const start = 0;
586 ToStatus(XPRSaddrows64(xpress_model_, 1, colind.size(), &sense, &rhs,
587 &rng, &start, colind.data(), rowcoef.data())));
588 if (qcol1.size() > 0) {
589 int const ret = XPRSaddqmatrix64(xpress_model_, oldRows, qcol1.size(),
590 qcol1.data(), qcol2.data(), qcoef.data());
591 if (ret != 0) {
592 XPRSdelrows(xpress_model_, 1, &oldRows);
593 return ToStatus(ret);
594 }
595 }
596 return absl::OkStatus();
597}
598
599absl::Status Xpress::WriteProb(std::string const& filename,
600 std::string const& flags) {
601 return ToStatus(
602 XPRSwriteprob(xpress_model_, filename.c_str(), flags.c_str()));
603}
604
605absl::Status Xpress::SaveAs(std::string const& filename) {
606 return ToStatus(XPRSsaveas(xpress_model_, filename.c_str()));
607}
608
609absl::Status Xpress::GetLB(absl::Span<double> lb, int first, int last) {
610 return ToStatus(XPRSgetlb(xpress_model_, lb.data(), first, last));
611}
612absl::Status Xpress::GetUB(absl::Span<double> ub, int first, int last) {
613 return ToStatus(XPRSgetub(xpress_model_, ub.data(), first, last));
614}
615absl::Status Xpress::GetColType(absl::Span<char> ctype, int first, int last) {
616 return ToStatus(XPRSgetcoltype(xpress_model_, ctype.data(), first, last));
617}
618
619absl::Status Xpress::ChgBounds(absl::Span<int const> colind,
620 absl::Span<char const> bndtype,
621 absl::Span<double const> bndval) {
622 if (colind.size() != bndtype.size() || colind.size() != bndval.size())
623 return absl::InvalidArgumentError("inconsitent data to ChgBounds()");
624 if (checkInt32Overflow(colind.size()))
625 return absl::InvalidArgumentError(
626 "XPRESS cannot handle more than 2^31 bound changes");
627 return ToStatus(XPRSchgbounds(xpress_model_, colind.size(), colind.data(),
628 bndtype.data(), bndval.data()));
629}
630absl::Status Xpress::ChgColType(absl::Span<int const> colind,
631 absl::Span<char const> coltype) {
632 if (colind.size() != coltype.size())
633 return absl::InvalidArgumentError("inconsitent data to ChgColType()");
634 if (checkInt32Overflow(colind.size()))
635 return absl::InvalidArgumentError(
636 "XPRESS cannot handle more than 2^31 type changes");
637 return ToStatus(XPRSchgcoltype(xpress_model_, colind.size(), colind.data(),
638 coltype.data()));
639}
640
641} // namespace operations_research::math_opt
#define ASSIGN_OR_RETURN(lhs, rexpr)
#define RETURN_IF_ERROR(expr)
absl::StatusOr< bool > IsMIP() const
Definition g_xpress.cc:416
absl::Status GetUB(absl::Span< double > ub, int first, int last)
Definition g_xpress.cc:612
absl::StatusOr< std::string > GetStrControl(int control) const
Definition g_xpress.cc:324
absl::Status AddCbChecktime(int(XPRS_CC *cb)(XPRSprob, void *), void *cbdata, int prio=0)
Definition g_xpress.cc:96
absl::Status ChgBounds(absl::Span< int const > colind, absl::Span< char const > bndtype, absl::Span< double const > bndval)
Definition g_xpress.cc:619
absl::Status RemoveCbChecktime(int(XPRS_CC *cb)(XPRSprob, void *), void *cbdata=nullptr)
Definition g_xpress.cc:101
absl::Status ChgCoeffs(absl::Span< const int > rowind, absl::Span< const int > colind, absl::Span< const double > values)
Definition g_xpress.cc:244
absl::Status ChgColType(absl::Span< int const > colind, absl::Span< char const > coltype)
Definition g_xpress.cc:630
absl::Status GetDuals(int *p_status, std::optional< absl::Span< double > > const &duals, int first, int last)
Definition g_xpress.cc:424
absl::StatusOr< std::vector< double > > GetVarUb() const
Definition g_xpress.cc:402
absl::Status GetColType(absl::Span< char > ctype, int first, int last)
Definition g_xpress.cc:615
absl::Status SetIntControl(int control, int value)
Definition g_xpress.cc:287
absl::Status Interrupt(int reason)
Definition g_xpress.cc:412
absl::Status SetStartingBasis(std::vector< int > &rowBasis, std::vector< int > &colBasis) const
Definition g_xpress.cc:383
absl::Status GetLB(absl::Span< double > lb, int first, int last)
Definition g_xpress.cc:609
absl::Status SetIndicators(absl::Span< int const > rowind, absl::Span< int const > colind, absl::Span< int const > complement)
Definition g_xpress.cc:535
absl::Status AddRows(absl::Span< char const > rowtype, absl::Span< double const > rhs, absl::Span< double const > rng, absl::Span< XPRSint64 const > start, absl::Span< int const > colind, absl::Span< double const > rowcoef)
Definition g_xpress.cc:553
absl::StatusOr< int > GetDualStatus() const
Definition g_xpress.cc:363
absl::StatusOr< int > GetIntAttr(int attribute) const
Definition g_xpress.cc:340
absl::Status RemoveCbMessage(void(XPRS_CC *cb)(XPRSprob, void *, char const *, int, int), void *cbdata=nullptr)
Definition g_xpress.cc:90
absl::Status SetProbName(absl::string_view name)
Definition g_xpress.cc:75
absl::Status GetLpSol(absl::Span< double > primals, absl::Span< double > duals, absl::Span< double > reducedCosts)
Definition g_xpress.cc:256
absl::Status AddConstrs(absl::Span< const char > sense, absl::Span< const double > rhs, absl::Span< const double > rng)
Definition g_xpress.cc:181
absl::Status AddVars(std::size_t count, absl::Span< const double > obj, absl::Span< const double > lb, absl::Span< const double > ub, absl::Span< const char > vtype)
Definition g_xpress.cc:128
absl::Status AddCbMessage(void(XPRS_CC *cb)(XPRSprob, void *, char const *, int, int), void *cbdata, int prio=0)
Definition g_xpress.cc:84
absl::Status SetLinearObjective(double constant, absl::Span< const int > col_index, absl::Span< const double > obj_coeffs)
Definition g_xpress.cc:223
absl::Status GetControlInfo(char const *name, int *p_id, int *p_type) const
Definition g_xpress.cc:275
absl::StatusOr< double > CalculateObjectiveN(int objidx, double const *solution)
Definition g_xpress.cc:510
static absl::StatusOr< std::unique_ptr< Xpress > > New(absl::string_view model_name)
Definition g_xpress.cc:67
absl::Status ResetIntControl(int control)
Definition g_xpress.cc:291
absl::Status LoadDirs(absl::Span< int const > cols, std::optional< absl::Span< int const > > const &prio, std::optional< absl::Span< char const > > const &dir, std::optional< absl::Span< double const > > const &up, std::optional< absl::Span< double const > > const &down)
Definition g_xpress.cc:465
absl::Status SetIntControl64(int control, int64_t value)
Definition g_xpress.cc:309
absl::StatusOr< int64_t > GetIntControl64(int control) const
Definition g_xpress.cc:301
absl::StatusOr< int > AddObjective(double constant, int ncols, absl::Span< int const > colind, absl::Span< double const > objcoef, int priority, double weight)
Definition g_xpress.cc:485
absl::Status SetStrControl(int control, std::string const &value)
Definition g_xpress.cc:336
absl::Status Optimize(std::string const &flags="", int *p_solvestatus=nullptr, int *p_solstatus=nullptr)
Definition g_xpress.cc:267
absl::Status LpOptimize(std::string flags)
Definition g_xpress.cc:252
absl::Status AddNames(int type, absl::Span< const char > names, int first, int last)
Definition g_xpress.cc:118
absl::Status SaveAs(std::string const &filename)
Definition g_xpress.cc:605
absl::Status SetQuadraticObjective(absl::Span< const int > colind1, absl::Span< const int > colind2, absl::Span< const double > coefficients)
Definition g_xpress.cc:236
absl::StatusOr< int > GetIntControl(int control) const
Definition g_xpress.cc:280
absl::Status GetSolution(int *p_status, std::optional< absl::Span< double > > const &x, int first, int last)
Definition g_xpress.cc:430
absl::StatusOr< double > GetDoubleAttr(int attribute) const
Definition g_xpress.cc:347
absl::Status SetObjectiveIntControl(int obj, int control, int value)
Definition g_xpress.cc:478
absl::Status LoadDelayedRows(absl::Span< int const > rows)
Definition g_xpress.cc:458
absl::Status SetDblControl(int control, double value)
Definition g_xpress.cc:320
absl::Status SetObjectiveDoubleControl(int obj, int control, double value)
Definition g_xpress.cc:481
absl::StatusOr< double > GetObjectiveDoubleAttr(int objidx, int attribute) const
Definition g_xpress.cc:354
absl::StatusOr< double > GetDblControl(int control) const
Definition g_xpress.cc:313
absl::Status GetRedCosts(int *p_status, std::optional< absl::Span< double > > const &dj, int first, int last)
Definition g_xpress.cc:436
absl::Status WriteProb(std::string const &filename, std::string const &flags="")
Definition g_xpress.cc:599
absl::Status AddMIPSol(absl::Span< double const > vals, absl::Span< int const > colind, char const *name=nullptr)
Definition g_xpress.cc:446
absl::Status GetBasis(std::vector< int > &rowBasis, std::vector< int > &colBasis) const
Definition g_xpress.cc:373
absl::Status AddQRow(char sense, double rhs, double rng, absl::Span< int const > colind, absl::Span< double const > rowcoef, absl::Span< int const > qcol1, absl::Span< int const > qcol2, absl::Span< double const > qcoef)
Definition g_xpress.cc:574
absl::Status SetObjectiveSense(bool maximize)
Definition g_xpress.cc:218
absl::StatusOr< std::vector< double > > GetVarLb() const
Definition g_xpress.cc:393
absl::Status AddSets(absl::Span< char const > settype, absl::Span< XPRSint64 const > start, absl::Span< int const > colind, absl::Span< double const > refval)
Definition g_xpress.cc:520
dual_gradient T(y - `dual_solution`) class DiagonalTrustRegionProblemFromQp
std::function< int(XPRSprob prob, int objidx)> XPRSdelobj
std::function< int(XPRSprob prob, int(XPRS_CC *f_checktime)(XPRSprob cbprob, void *cbdata), void *p)> XPRSremovecbchecktime
std::function< int(XPRSprob prob, int objidx, const double solution[], double *p_objval)> XPRScalcobjn
std::function< int(XPRSprob prob, int(XPRS_CC *f_checktime)(XPRSprob cbprob, void *cbdata), void *p, int priority)> XPRSaddcbchecktime
std::function< int(XPRSprob prob, int nrows, const int rowind[])> XPRSloaddelayedrows
std::function< int(XPRSprob prob, int attrib, int *p_value)> XPRSgetintattrib
std::function< int(XPRSprob prob, int ndirs, const int colind[], const int priority[], const char dir[], const double uppseudo[], const double downpseudo[])> XPRSloaddirs
std::function< int(XPRSprob prob, int ncoefs, const int objqcol1[], const int objqcol2[], const double objqcoef[])> XPRSchgmqobj
std::function< int(XPRSprob prob, void(XPRS_CC *f_message)(XPRSprob cbprob, void *cbdata, const char *msg, int msglen, int msgtype), void *p)> XPRSremovecbmessage
std::function< int(XPRSprob prob, char coltype[], int first, int last)> XPRSgetcoltype
std::function< int(XPRSprob prob, int attrib, double *p_value)> XPRSgetdblattrib
std::function< int(XPRSprob prob, int *status, double djs[], int first, int last)> XPRSgetredcosts
std::function< int(XPRSprob prob, const char *filename, const char *flags)> XPRSwriteprob
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
Select next search node to expand Select next item_i to add this new search node to the search Generate a new search node where item_i is not in the knapsack Check validity of this new partial solution(using propagators) - If valid
bool initXpressEnv(bool verbose, int xpress_oem_license_key)
init XPRESS environment.
std::function< int(XPRSprob prob, int length, const double solval[], const int colind[], const char *name)> XPRSaddmipsol
std::function< int(XPRSprob prob, int nbounds, const int colind[], const char bndtype[], const double bndval[])> XPRSchgbounds
std::function< int(XPRSprob prob, const int rowstat[], const int colstat[])> XPRSloadbasis
std::function< int(XPRSprob prob, int nrows, const int rowind[])> XPRSdelrows
std::function< int(XPRSprob prob, int ncols, const int colind[])> XPRSdelcols
std::function< int(XPRSprob prob, int control, double *p_value)> XPRSgetdblcontrol
std::function< int(XPRSprob prob, int objidx, int control, int value)> XPRSsetobjintcontrol
std::function< int(XPRSprob prob, double lb[], int first, int last)> XPRSgetlb
std::function< int(XPRSprob prob, const char *flags, int *solvestatus, int *solstatus)> XPRSoptimize
std::function< int(XPRSprob prob, int control, int *p_value)> XPRSgetintcontrol
std::function< int(XPRSprob prob, int ncols, const int colind[], const char coltype[])> XPRSchgcoltype
std::function< int(XPRSprob prob, int nrows, const int rowind[], const int colind[], const int complement[])> XPRSsetindicators
std::function< int(XPRSprob prob, const char *name, int *p_id, int *p_type)> XPRSgetcontrolinfo
std::function< int(XPRSprob prob, double x[], double slack[], double duals[], double djs[])> XPRSgetlpsol
std::function< int(XPRSprob prob, int control, XPRSint64 *p_value)> XPRSgetintcontrol64
std::function< int(XPRSprob prob)> XPRSpostsolve
std::function< int(XPRSprob prob, int type, const char names[], int first, int last)> XPRSaddnames
std::function< int(void)> XPRSfree
std::function< int(XPRSprob prob, int reason)> XPRSinterrupt
std::function< int(XPRSprob prob, const char *filename)> XPRSsaveas
std::function< int(XPRSprob prob, int nsets, XPRSint64 nelems, const char settype[], const XPRSint64 start[], const int colind[], const double refval[])> XPRSaddsets64
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, int control, double value)> XPRSsetdblcontrol
std::function< int(XPRSprob prob, XPRSint64 ncoefs, const int rowind[], const int colind[], const double rowcoef[])> XPRSchgmcoef64
std::function< int(XPRSprob prob, int *status, double x[], int first, int last)> XPRSgetsolution
std::function< int(XPRSprob prob, double ub[], int first, int last)> XPRSgetub
std::function< int(XPRSprob prob, int control, const char *value)> XPRSsetstrcontrol
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, int control, char *value, int maxbytes, int *p_nbytes)> XPRSgetstringcontrol
std::function< int(XPRSprob prob, int row, int ncoefs, const int rowqcol1[], int const rowqcol2[], const double rowqcoef[])> XPRSaddqmatrix64
std::function< int(XPRSprob prob, int ncols, const int colind[], const double objcoef[], int priority, double weight)> XPRSaddobj
std::function< int(XPRSprob prob, int nrows, int ncoefs, const char rowtype[], const double rhs[], const double rng[], const XPRSint64 start[], const int colind[], const double rowcoef[])> XPRSaddrows64
std::function< int(XPRSprob prob, int objidx, int attrib, double *p_value)> XPRSgetobjdblattrib
std::function< int(XPRSprob prob, int objidx, int control, double value)> XPRSsetobjdblcontrol
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 control, XPRSint64 value)> XPRSsetintcontrol64
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 INT32_MAX
Definition parser.yy.cc:310
#define XPRS_OBJECTIVES
#define XPRS_ORIGINALINDICATORS
#define XPRS_OBJ_MAXIMIZE
#define XPRS_OBJECTIVE_RHS
#define XPRS_ORIGINALROWS
#define XPRS_ORIGINALSETS
#define XPRS_ORIGINALCOLS
#define XPRSint64
struct xo_prob_struct * XPRSprob
#define XPRS_MAXPROBNAMELENGTH
#define XPRS_LPITERLIMIT
#define XPRS_ORIGINALMIPENTS
#define XPRS_BARITERLIMIT
#define XPRS_STOP_USER
#define XPRS_CC
#define XPRS_OBJ_MINIMIZE