14 #ifndef OR_TOOLS_MATH_OPT_SOLVERS_GUROBI_SOLVER_H_
15 #define OR_TOOLS_MATH_OPT_SOLVERS_GUROBI_SOLVER_H_
24 #include "absl/container/flat_hash_map.h"
25 #include "absl/container/flat_hash_set.h"
26 #include "absl/status/status.h"
27 #include "absl/status/statusor.h"
28 #include "absl/time/time.h"
29 #include "absl/types/span.h"
32 #include "ortools/math_opt/callback.pb.h"
37 #include "ortools/math_opt/model.pb.h"
38 #include "ortools/math_opt/model_parameters.pb.h"
39 #include "ortools/math_opt/model_update.pb.h"
40 #include "ortools/math_opt/parameters.pb.h"
41 #include "ortools/math_opt/result.pb.h"
42 #include "ortools/math_opt/solution.pb.h"
46 #include "ortools/math_opt/sparse_containers.pb.h"
53 static absl::StatusOr<std::unique_ptr<GurobiSolver>>
New(
54 const ModelProto& input_model,
57 absl::StatusOr<SolveResultProto>
Solve(
59 const ModelSolveParametersProto& model_parameters,
61 const CallbackRegistrationProto& callback_registration,
Callback cb,
63 absl::StatusOr<bool>
Update(
const ModelUpdateProto& model_update)
override;
66 struct GurobiCallbackData {
69 : callback_input(std::move(callback_input)),
70 local_interrupter(local_interrupter) {}
85 absl::Status
status = absl::OkStatus();
91 using VariableId = int64_t;
92 using LinearConstraintId = int64_t;
93 using QuadraticConstraintId = int64_t;
94 using Sos1ConstraintId = int64_t;
95 using Sos2ConstraintId = int64_t;
96 using IndicatorConstraintId = int64_t;
97 using AnyConstraintId = int64_t;
98 using GurobiVariableIndex = int;
99 using GurobiLinearConstraintIndex = int;
100 using GurobiQuadraticConstraintIndex = int;
101 using GurobiSosConstraintIndex = int;
105 using GurobiGeneralConstraintIndex = int;
106 using GurobiAnyConstraintIndex = int;
108 static constexpr GurobiVariableIndex kUnspecifiedIndex = -1;
109 static constexpr GurobiAnyConstraintIndex kUnspecifiedConstraint = -2;
110 static constexpr
double kInf = std::numeric_limits<double>::infinity();
118 struct LinearConstraintData {
119 GurobiLinearConstraintIndex constraint_index = kUnspecifiedConstraint;
121 GurobiVariableIndex slack_index = kUnspecifiedIndex;
126 struct SosConstraintData {
127 GurobiSosConstraintIndex constraint_index = kUnspecifiedConstraint;
128 std::vector<GurobiVariableIndex> slack_variables;
129 std::vector<GurobiLinearConstraintIndex> slack_constraints;
132 struct IndicatorConstraintData {
135 GurobiGeneralConstraintIndex constraint_index;
138 int64_t indicator_variable_id;
141 struct SolutionClaims {
142 bool primal_feasible_solution_exists;
143 bool dual_feasible_solution_exists;
146 struct SolutionsAndClaims {
147 std::vector<SolutionProto> solutions;
148 SolutionClaims solution_claims;
151 template <
typename SolutionType>
152 struct SolutionAndClaim {
153 std::optional<SolutionType> solution;
154 bool feasible_solution_exists =
false;
159 absl::StatusOr<ProblemStatusProto> GetProblemStatus(
160 const int grb_termination,
const SolutionClaims solution_claims);
161 absl::StatusOr<SolveResultProto> ExtractSolveResultProto(
162 absl::Time
start,
const ModelSolveParametersProto& model_parameters);
163 absl::Status FillRays(
const ModelSolveParametersProto& model_parameters,
164 const SolutionClaims solution_claims,
165 SolveResultProto& result);
166 absl::StatusOr<GurobiSolver::SolutionsAndClaims> GetSolutions(
167 const ModelSolveParametersProto& model_parameters);
168 absl::StatusOr<SolveStatsProto> GetSolveStats(absl::Time
start,
169 SolutionClaims solution_claims);
171 absl::StatusOr<double> GetBestDualBound();
172 absl::StatusOr<double> GetBestPrimalBound(
bool has_primal_feasible_solution);
173 bool PrimalSolutionQualityAvailable()
const;
174 absl::StatusOr<double> GetPrimalSolutionQuality()
const;
177 absl::StatusOr<bool> IsMaximize()
const;
179 static absl::StatusOr<TerminationProto> ConvertTerminationReason(
180 int gurobi_status, SolutionClaims solution_claims);
184 absl::StatusOr<SolutionsAndClaims> GetLpSolution(
185 const ModelSolveParametersProto& model_parameters);
188 absl::StatusOr<SolutionsAndClaims> GetQpSolution(
189 const ModelSolveParametersProto& model_parameters);
192 absl::StatusOr<SolutionsAndClaims> GetQcpSolution(
193 const ModelSolveParametersProto& model_parameters);
196 absl::StatusOr<SolutionsAndClaims> GetMipSolutions(
197 const ModelSolveParametersProto& model_parameters);
200 absl::StatusOr<SolutionAndClaim<PrimalSolutionProto>>
201 GetConvexPrimalSolutionIfAvailable(
202 const ModelSolveParametersProto& model_parameters);
203 absl::StatusOr<SolutionAndClaim<DualSolutionProto>>
204 GetLpDualSolutionIfAvailable(
205 const ModelSolveParametersProto& model_parameters);
206 absl::StatusOr<std::optional<BasisProto>> GetBasisIfAvailable();
208 absl::Status SetParameters(
const SolveParametersProto&
parameters);
209 absl::Status AddNewLinearConstraints(
210 const LinearConstraintsProto& constraints);
211 absl::Status AddNewQuadraticConstraints(
212 const google::protobuf::Map<QuadraticConstraintId,
213 QuadraticConstraintProto>& constraints);
214 absl::Status AddNewSosConstraints(
215 const google::protobuf::Map<AnyConstraintId, SosConstraintProto>&
218 absl::flat_hash_map<int64_t, SosConstraintData>& constraints_map);
219 absl::Status AddNewIndicatorConstraints(
220 const google::protobuf::Map<IndicatorConstraintId,
221 IndicatorConstraintProto>& constraints);
222 absl::Status AddNewVariables(
const VariablesProto& new_variables);
223 absl::Status AddNewSlacks(
224 const std::vector<LinearConstraintData*>& new_slacks);
225 absl::Status ChangeCoefficients(
const SparseDoubleMatrixProto& matrix);
227 absl::Status ResetQuadraticObjectiveTerms(
228 const SparseDoubleMatrixProto& terms);
231 absl::Status UpdateQuadraticObjectiveTerms(
232 const SparseDoubleMatrixProto& terms);
233 absl::Status LoadModel(
const ModelProto& input_model);
235 absl::Status UpdateDoubleListAttribute(
const SparseDoubleVectorProto& update,
236 const char* attribute_name,
238 absl::Status UpdateInt32ListAttribute(
const SparseInt32VectorProto& update,
239 const char* attribute_name,
242 struct DeletedIndices {
243 std::vector<GurobiVariableIndex> variables;
244 std::vector<GurobiLinearConstraintIndex> linear_constraints;
245 std::vector<GurobiQuadraticConstraintIndex> quadratic_constraints;
246 std::vector<GurobiSosConstraintIndex> sos_constraints;
247 std::vector<GurobiGeneralConstraintIndex> general_constraints;
250 void UpdateGurobiIndices(
const DeletedIndices& deleted_indices);
251 absl::Status UpdateLinearConstraints(
252 const LinearConstraintUpdatesProto& update,
253 std::vector<GurobiVariableIndex>& deleted_variables_index);
255 int get_model_index(GurobiVariableIndex
index)
const {
return index; }
256 int get_model_index(
const LinearConstraintData&
index)
const {
257 return index.constraint_index;
264 template <
typename T>
265 void GurobiVectorToSparseDoubleVector(
266 absl::Span<const double> gurobi_values,
const T& map,
267 SparseDoubleVectorProto& result,
268 const SparseVectorFilterProto& filter)
const;
269 absl::StatusOr<BasisProto> GetGurobiBasis();
270 absl::Status SetGurobiBasis(
const BasisProto& basis);
271 absl::StatusOr<DualRayProto> GetGurobiDualRay(
272 const SparseVectorFilterProto& linear_constraints_filter,
273 const SparseVectorFilterProto& variables_filter,
bool is_maximize);
275 absl::StatusOr<bool> IsMIP()
const;
277 absl::StatusOr<bool> IsQP()
const;
279 absl::StatusOr<bool> IsQCP()
const;
281 absl::StatusOr<std::unique_ptr<GurobiCallbackData>> RegisterCallback(
282 const CallbackRegistrationProto& registration,
Callback cb,
287 absl::StatusOr<InvertedBounds> ListInvertedBounds()
const;
291 absl::StatusOr<InvalidIndicators> ListInvalidIndicators()
const;
293 const std::unique_ptr<Gurobi> gurobi_;
307 linear_constraints_map_;
310 absl::flat_hash_map<QuadraticConstraintId, GurobiQuadraticConstraintIndex>
311 quadratic_constraints_map_;
314 absl::flat_hash_map<Sos1ConstraintId, SosConstraintData>
315 sos1_constraints_map_;
318 absl::flat_hash_map<Sos2ConstraintId, SosConstraintData>
319 sos2_constraints_map_;
324 absl::flat_hash_map<IndicatorConstraintId,
325 std::optional<IndicatorConstraintData>>
326 indicator_constraints_map_;
333 int num_gurobi_variables_ = 0;
335 int num_gurobi_lin_cons_ = 0;
337 int num_gurobi_quad_cons_ = 0;
339 int num_gurobi_sos_cons_ = 0;
341 int num_gurobi_gen_cons_ = 0;
348 absl::flat_hash_map<std::pair<VariableId, VariableId>,
double>
349 quadratic_objective_coefficients_;
355 absl::flat_hash_set<VariableId> undeletable_variables_;
357 static constexpr
int kGrbBasicConstraint = 0;
358 static constexpr
int kGrbNonBasicConstraint = -1;
absl::StatusOr< bool > Update(const ModelUpdateProto &model_update) override
static absl::StatusOr< std::unique_ptr< GurobiSolver > > New(const ModelProto &input_model, const SolverInterface::InitArgs &init_args)
absl::StatusOr< SolveResultProto > Solve(const SolveParametersProto ¶meters, const ModelSolveParametersProto &model_parameters, MessageCallback message_cb, const CallbackRegistrationProto &callback_registration, Callback cb, SolveInterrupter *interrupter) override
std::function< void(const std::vector< std::string > &)> MessageCallback
std::function< absl::StatusOr< CallbackResultProto >(const CallbackDataProto &)> Callback
Collection of objects used to extend the Constraint Solver library.