OR-Tools  9.3
gscip_solver.h
Go to the documentation of this file.
1// Copyright 2010-2021 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 OR_TOOLS_MATH_OPT_SOLVERS_GSCIP_SOLVER_H_
15#define OR_TOOLS_MATH_OPT_SOLVERS_GSCIP_SOLVER_H_
16
17#include <cstdint>
18#include <memory>
19#include <string>
20
21#include "absl/container/flat_hash_map.h"
22#include "absl/container/flat_hash_set.h"
23#include "absl/status/status.h"
24#include "absl/status/statusor.h"
25#include "absl/types/span.h"
26#include "ortools/gscip/gscip.h"
27#include "ortools/gscip/gscip.pb.h"
29#include "ortools/math_opt/callback.pb.h"
33#include "ortools/math_opt/model.pb.h"
34#include "ortools/math_opt/model_parameters.pb.h"
35#include "ortools/math_opt/model_update.pb.h"
36#include "ortools/math_opt/parameters.pb.h"
37#include "ortools/math_opt/result.pb.h"
38#include "ortools/math_opt/sparse_containers.pb.h"
39#include "scip/type_cons.h"
40#include "scip/type_var.h"
41
42namespace operations_research {
43namespace math_opt {
44
46 public:
47 static absl::StatusOr<std::unique_ptr<SolverInterface>> New(
48 const ModelProto& model, const InitArgs& init_args);
49
50 absl::StatusOr<SolveResultProto> Solve(
51 const SolveParametersProto& parameters,
52 const ModelSolveParametersProto& model_parameters,
53 MessageCallback message_cb,
54 const CallbackRegistrationProto& callback_registration, Callback cb,
55 SolveInterrupter* interrupter) override;
56 absl::Status Update(const ModelUpdateProto& model_update) override;
57 bool CanUpdate(const ModelUpdateProto& model_update) override;
58
59 // Returns the merged parameters and a list of warnings for unsupported
60 // parameters.
61 static absl::StatusOr<GScipParameters> MergeParameters(
62 const SolveParametersProto& solve_parameters);
63
64 private:
65 // Event handler that it used to call SCIPinterruptSolve() is a safe manner.
66 //
67 // At the start of SCIPsolve(), SCIP resets `userinterrupt` to false. It does
68 // the same in SCIPpresolve(), which is called at the beginning of SCIPsolve()
69 // but also at the beginning of each restart. the `userinterrupt` can also be
70 // reset when the transformed problem is freed when the parameter
71 // "misc/resetstat" is used. On top of that, it is not possible to call
72 // SCIPinterruptSolve() in SCIP_STAGE_INITSOLVE stage; which occurs in the
73 // middle of the solve and at restarts.
74 //
75 // If this was no enough, SCIPinterruptSolve() calls SCIPcheckStage() which is
76 // not thread-safe.
77 //
78 // As a consequence, although it is possible to call SCIPinterruptSolve() from
79 // another thread, it is unreliable at best. Here we take a safer approach: we
80 // call it only from the Exec() of an even handler. This solves all thread
81 // safety issues and, if we have been careful, also ensures we don't call it
82 // in the wrong stage. This also solves the issue the multiple resets of the
83 // `userinterrupt` flag since each time we are called after the interrupter
84 // has been triggered, we simply call SCIPinterruptSolve() until SCIP finally
85 // listens.
86 struct InterruptEventHandler : public GScipEventHandler {
87 InterruptEventHandler();
88
89 SCIP_RETCODE Init(GScip* gscip) override;
90 SCIP_RETCODE Execute(GScipEventHandlerContext) override;
91
92 // Calls SCIPinterruptSolve() if the interrupter is set and triggered and
93 // SCIP is in a valid stage for that.
94 SCIP_RETCODE TryCallInterruptIfNeeded(GScip* gscip);
95
96 // This will be set before SCIPsolve() is called and reset after the end of
97 // the call. It may be null when the user does not provide an interrupter;
98 // in that case we don't register any event.
99 SolveInterrupter* interrupter = nullptr;
100 };
101
102 explicit GScipSolver(std::unique_ptr<GScip> gscip);
103
104 // Adds the new variables.
105 absl::Status AddVariables(const VariablesProto& variables,
106 const absl::flat_hash_map<int64_t, double>&
107 linear_objective_coefficients);
108
109 // Update existing variables' parameters.
110 absl::Status UpdateVariables(const VariableUpdatesProto& variable_updates);
111
112 // Adds the new linear constraints.
113 absl::Status AddLinearConstraints(
114 const LinearConstraintsProto& linear_constraints,
115 const SparseDoubleMatrixProto& linear_constraint_matrix);
116
117 // Updates the existing constraints and the coefficients of the existing
118 // variables of these constraints.
119 absl::Status UpdateLinearConstraints(
120 const LinearConstraintUpdatesProto linear_constraint_updates,
121 const SparseDoubleMatrixProto& linear_constraint_matrix,
122 std::optional<int64_t> first_new_var_id,
123 std::optional<int64_t> first_new_cstr_id);
124
125 absl::flat_hash_set<SCIP_VAR*> LookupAllVariables(
126 absl::Span<const int64_t> variable_ids);
127 absl::StatusOr<SolveResultProto> CreateSolveResultProto(
128 GScipResult gscip_result,
129 const ModelSolveParametersProto& model_parameters,
130 std::optional<double> cutoff);
131
132 // Returns the ids of variables and linear constraints with inverted bounds.
133 InvertedBounds ListInvertedBounds() const;
134
135 const std::unique_ptr<GScip> gscip_;
136 InterruptEventHandler interrupt_event_handler_;
137 absl::flat_hash_map<int64_t, SCIP_VAR*> variables_;
138 absl::flat_hash_map<int64_t, SCIP_CONS*> linear_constraints_;
139};
140
141} // namespace math_opt
142} // namespace operations_research
143
144#endif // OR_TOOLS_MATH_OPT_SOLVERS_GSCIP_SOLVER_H_
bool CanUpdate(const ModelUpdateProto &model_update) override
absl::Status Update(const ModelUpdateProto &model_update) override
static absl::StatusOr< std::unique_ptr< SolverInterface > > New(const ModelProto &model, const InitArgs &init_args)
absl::StatusOr< SolveResultProto > Solve(const SolveParametersProto &parameters, const ModelSolveParametersProto &model_parameters, MessageCallback message_cb, const CallbackRegistrationProto &callback_registration, Callback cb, SolveInterrupter *interrupter) override
static absl::StatusOr< GScipParameters > MergeParameters(const SolveParametersProto &solve_parameters)
std::function< void(const std::vector< std::string > &)> MessageCallback
std::function< absl::StatusOr< CallbackResultProto >(const CallbackDataProto &)> Callback
SatParameters parameters
absl::Span< const int64_t > variable_ids
GRBmodel * model
Collection of objects used to extend the Constraint Solver library.