Google OR-Tools v9.15
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
xpress_solver.h
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
14#ifndef ORTOOLS_MATH_OPT_SOLVERS_XPRESS_SOLVER_H_
15#define ORTOOLS_MATH_OPT_SOLVERS_XPRESS_SOLVER_H_
16
17#include <cstdint>
18#include <memory>
19#include <optional>
20#include <string>
21
22#include "absl/status/status.h"
23#include "absl/status/statusor.h"
24#include "absl/time/time.h"
25#include "absl/types/span.h"
41
43
44// Interface to FICO XPRESS solver
45class XpressSolver : public SolverInterface {
46 public:
47 // Creates the XPRESS solver and loads the model into it
48 static absl::StatusOr<std::unique_ptr<XpressSolver>> New(
49 const ModelProto& input_model,
50 const SolverInterface::InitArgs& init_args);
51
52 // Solves the optimization problem
53 absl::StatusOr<SolveResultProto> Solve(
54 const SolveParametersProto& parameters,
55 const ModelSolveParametersProto& model_parameters,
56 MessageCallback message_cb,
57 const CallbackRegistrationProto& callback_registration, Callback cb,
58 const SolveInterrupter* interrupter) override;
59
60 // Updates the problem (not implemented yet)
61 absl::StatusOr<bool> Update(const ModelUpdateProto& model_update) override;
62
63 // Computes the infeasible subsystem (not implemented yet)
64 absl::StatusOr<ComputeInfeasibleSubsystemResultProto>
66 MessageCallback message_cb,
67 const SolveInterrupter* interrupter) override;
68
69 private:
70 explicit XpressSolver(std::unique_ptr<Xpress> g_xpress, bool extract_names);
71
72 public:
73 // For easing reading the code, we declare these types:
74 using VarId = int64_t;
75 using AuxiliaryObjectiveId = int64_t;
76 using LinearConstraintId = int64_t;
77 using QuadraticConstraintId = int64_t;
79 using Sos1ConstraintId = int64_t;
80 using Sos2ConstraintId = int64_t;
81 using IndicatorConstraintId = int64_t;
82 using AnyConstraintId = int64_t;
90
91 private:
92 static constexpr XpressVariableIndex kUnspecifiedIndex = -1;
93 static constexpr XpressAnyConstraintIndex kUnspecifiedConstraint = -2;
94 static constexpr double kPlusInf = XPRS_PLUSINFINITY;
95 static constexpr double kMinusInf = XPRS_MINUSINFINITY;
96
97 static bool isFinite(double value) {
98 return value < kPlusInf && value > kMinusInf;
99 }
100
101 // Data associated with each linear constraint
102 public:
105 double lower_bound = kMinusInf;
106 double upper_bound = kPlusInf;
107 };
108
109 private:
110 absl::StatusOr<SolveResultProto> ExtractSolveResultProto(
111 absl::Time start, const ModelSolveParametersProto& model_parameters,
112 const SolveParametersProto& solve_parameters);
113 absl::Status ExtendWithMultiobj(SolutionProto& solution);
114 absl::Status AppendSolution(SolveResultProto& solve_result,
115 const ModelSolveParametersProto& model_parameters,
116 const SolveParametersProto& solve_parameters);
117 absl::StatusOr<SolveStatsProto> GetSolveStats(absl::Time start) const;
118
119 absl::StatusOr<double> GetBestPrimalBound() const;
120 absl::StatusOr<double> GetBestDualBound() const;
121
122 absl::StatusOr<TerminationProto> ConvertTerminationReason(
123 double best_primal_bound, double best_dual_bound) const;
124
125 bool isPrimalFeasible() const;
126 bool isDualFeasible() const;
127
128 void ExtractBounds(double lb, double ub, char& sense, double& rhs,
129 double& rng);
130 void ExtractLinear(SparseDoubleVectorProto const& expr,
131 std::vector<int>& colind, std::vector<double>& coef);
132 void ExtractQuadratic(QuadraticConstraintProto const& expr,
133 std::vector<int>& lin_colind,
134 std::vector<double>& lin_coef,
135 std::vector<int>& quad_col1,
136 std::vector<int>& quad_col2,
137 std::vector<double>& quad_coef);
138
139 absl::StatusOr<std::optional<BasisProto>> GetBasisIfAvailable(
140 const SolveParametersProto& parameters);
141
142 absl::Status AddNewLinearConstraints(
143 const LinearConstraintsProto& constraints);
144 absl::Status AddNewVariables(const VariablesProto& new_variables);
145 absl::Status AddObjective(const ObjectiveProto& objective,
146 std::optional<AuxiliaryObjectiveId> objective_id,
147 bool multiobj);
148 absl::Status AddSOS(
149 const google::protobuf::Map<AnyConstraintId, SosConstraintProto>& sets,
150 bool sos1);
151 absl::Status AddIndicators(
152 const google::protobuf::Map<IndicatorConstraintId,
153 IndicatorConstraintProto>& indicators);
154 absl::Status AddQuadraticConstraints(
155 const google::protobuf::Map<QuadraticConstraintId,
156 QuadraticConstraintProto>& constraints);
157 absl::Status AddSecondOrderConeConstraints(
158 const google::protobuf::Map<SecondOrderConeConstraintId,
159 SecondOrderConeConstraintProto>& constraints);
160 absl::Status ChangeCoefficients(const SparseDoubleMatrixProto& matrix);
161
162 absl::Status LoadModel(const ModelProto& input_model);
163
164 // Fills in result with the values in xpress_values aided by the index
165 // conversion from map which should be either variables_map_ or
166 // linear_constraints_map_ as appropriate. Only key/value pairs that passes
167 // the filter predicate are added.
168 template <typename T>
169 void XpressVectorToSparseDoubleVector(
170 absl::Span<const double> xpress_values, const T& map,
172 const SparseVectorFilterProto& filter) const;
173
174 const std::unique_ptr<Xpress> xpress_;
175 bool const extract_names_;
176
177 // Internal correspondence from variable proto IDs to Xpress-numbered
178 // variables.
180 // Internal correspondence from linear constraint proto IDs to
181 // Xpress-numbered linear constraint and extra information.
183 linear_constraints_map_;
184 // Internal correspondence from objective proto IDs to Xpress-numbered
185 // objectives.
187 objectives_map_;
188 // Internal correspondence from SOS1 proto IDs to Xpress-numbered
189 // SOS1 constraints.
191 // Internal correspondence from SOS2 proto IDs to Xpress-numbered
192 // SOS2 constraints.
194 // Internal correspondence from indicator proto IDs to Xpress-numbered
195 // indicators.
197 indicator_map_;
198 // Internal correspondence from quadratic proto IDs to Xpress-numbered
199 // rows.
201 quad_constraints_map_;
202 // Internal correspondence from second order cone constraint proto IDs to
203 // Xpress-numbered rows.
205
206 int get_model_index(XpressVariableIndex index) const { return index; }
207 int get_model_index(const LinearConstraintData& index) const {
208 return index.constraint_index;
209 }
210 SolutionStatusProto getPrimalSolutionStatus() const;
211 SolutionStatusProto getDualSolutionStatus() const;
212 absl::StatusOr<InvertedBounds> ListInvertedBounds() const;
213
215 bool force_postsolve_ = false;
217 bool stop_after_lp_ = false;
226 bool nonbinary_indicator_ = false;
227 bool is_multiobj_ = false;
228 bool is_mip_ = false;
229 // Results of the last solve
230 int primal_sol_avail_ = XPRS_SOLAVAILABLE_NOTFOUND;
231 int dual_sol_avail_ = XPRS_SOLAVAILABLE_NOTFOUND;
232 // Information queried right after a solve and stored for solution reporting
233 int solvestatus_ = XPRS_SOLVESTATUS_UNSTARTED;
234 int solstatus_ = XPRS_SOLSTATUS_NOTFOUND;
235 int algorithm_ = XPRS_ALG_DEFAULT;
236 int optimizetypeused_ = -1;
237};
238
239} // namespace operations_research::math_opt
240
241#endif // ORTOOLS_MATH_OPT_SOLVERS_XPRESS_SOLVER_H_
std::function< void(const std::vector< std::string > &)> MessageCallback
std::function< absl::StatusOr< CallbackResultProto >( const CallbackDataProto &)> Callback
absl::StatusOr< SolveResultProto > Solve(const SolveParametersProto &parameters, const ModelSolveParametersProto &model_parameters, MessageCallback message_cb, const CallbackRegistrationProto &callback_registration, Callback cb, const SolveInterrupter *interrupter) override
absl::StatusOr< bool > Update(const ModelUpdateProto &model_update) override
absl::StatusOr< ComputeInfeasibleSubsystemResultProto > ComputeInfeasibleSubsystem(const SolveParametersProto &parameters, MessageCallback message_cb, const SolveInterrupter *interrupter) override
static absl::StatusOr< std::unique_ptr< XpressSolver > > New(const ModelProto &input_model, const SolverInterface::InitArgs &init_args)
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
#define XPRS_PLUSINFINITY
#define XPRS_ALG_DEFAULT
#define XPRS_SOLAVAILABLE_NOTFOUND
#define XPRS_SOLVESTATUS_UNSTARTED
#define XPRS_MINUSINFINITY
#define XPRS_SOLSTATUS_NOTFOUND