Google OR-Tools v9.11
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
solver_interface.h
Go to the documentation of this file.
1// Copyright 2010-2024 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_CORE_SOLVER_INTERFACE_H_
15#define OR_TOOLS_MATH_OPT_CORE_SOLVER_INTERFACE_H_
16
17#include <functional>
18#include <memory>
19#include <string>
20#include <vector>
21
22#include "absl/base/attributes.h"
23#include "absl/container/flat_hash_map.h"
24#include "absl/status/statusor.h"
25#include "absl/strings/string_view.h"
26#include "absl/synchronization/mutex.h"
27#include "ortools/math_opt/callback.pb.h"
29#include "ortools/math_opt/infeasible_subsystem.pb.h"
30#include "ortools/math_opt/model.pb.h"
31#include "ortools/math_opt/model_parameters.pb.h"
32#include "ortools/math_opt/model_update.pb.h"
33#include "ortools/math_opt/parameters.pb.h"
34#include "ortools/math_opt/result.pb.h"
36
37namespace operations_research {
38namespace math_opt {
39
40// Interface implemented by actual solvers.
41//
42// This interface is not meant to be used directly. The actual API is the one of
43// the Solver class. The Solver class validates the models before calling this
44// interface. It makes sure no concurrent calls happen on Solve(), CanUpdate()
45// and Update(). It makes sure no other function is called after Solve(),
46// Update() or a callback have failed.
47//
48// Implementations of this interface should not have public constructors but
49// instead have a static `New` function with the signature of Factory function
50// as defined below. They should register this factory using the macro
51// MATH_OPT_REGISTER_SOLVER().
53 public:
54 // Initialization arguments.
55 struct InitArgs {
56 // All parameters that can be stored in a proto and exchange with other
57 // processes.
58 SolverInitializerProto streamable;
59
60 // All parameters that can't be exchanged with another process. The caller
61 // keeps ownership of non_streamable.
63 };
64
65 // A callback function (if non null) for messages emitted by the solver.
66 //
67 // See Solver::MessageCallback documentation for details.
68 using MessageCallback = std::function<void(const std::vector<std::string>&)>;
69
70 // A callback function (if non null) is a function that validates its input
71 // and its output, and if fails, return a status. The invariant is that the
72 // solver implementation can rely on receiving valid data. The implementation
73 // of this interface must provide valid input (which will be validated) and
74 // in error, it will return a status (without actually calling the callback
75 // function). This is enforced in the solver.cc layer.
76 using Callback = std::function<absl::StatusOr<CallbackResultProto>(
77 const CallbackDataProto&)>;
78
79 // A factory builds a solver based on the input model and parameters.
80 //
81 // Implementation should have a static `New()` function with this signature
82 // and no public constructors.
83 //
84 // The implementation should assume the input ModelProto is valid and is free
85 // to CHECK-fail if this is not the case. It should also assume that the input
86 // init_args.streamable and init_args.non_streamable are also either not set
87 // of set to the arguments of the correct solver.
88 using Factory =
89 std::function<absl::StatusOr<std::unique_ptr<SolverInterface>>(
90 const ModelProto& model, const InitArgs& init_args)>;
91
92 SolverInterface() = default;
95 virtual ~SolverInterface() = default;
96
97 // Solves the current model (included all updates).
98 //
99 // All input arguments are ensured (by solver.cc) to be valid. Furthermore,
100 // since all parameters are references or functions (which could be a lambda
101 // expression), the implementation should not keep a reference or copy of
102 // them, as they may become invalid reference after the invocation if this
103 // function.
104 //
105 // Parameters `message_cb`, `cb` and `interrupter` are optional. They are
106 // nullptr when not set.
107 //
108 // When parameter `message_cb` is not null the value of
109 // parameters.enable_output should be ignored the solver should behave as it
110 // is was false (i.e. not print anything).
111 //
112 // When parameter `message_cb` is not null and the underlying solver does not
113 // supports message callbacks, it should ignore it.
114 //
115 // Solvers should return a InvalidArgumentError when called with events on
116 // callback_registration that are not supported by the solver for the type of
117 // model being solved (for example MIP events if the model is an LP, or events
118 // that are not emitted by the solver). Solvers should use
119 // CheckRegisteredCallbackEvents() to implement that.
120 virtual absl::StatusOr<SolveResultProto> Solve(
121 const SolveParametersProto& parameters,
122 const ModelSolveParametersProto& model_parameters,
123 MessageCallback message_cb,
124 const CallbackRegistrationProto& callback_registration, Callback cb,
125 const SolveInterrupter* interrupter) = 0;
126
127 // Updates the model to solve and returns true, or returns false if this
128 // update is not supported.
129 //
130 // The implementation should assume the input ModelUpdate is valid and is free
131 // to assert if this is not the case.
132 virtual absl::StatusOr<bool> Update(const ModelUpdateProto& model_update) = 0;
133
134 // Computes a infeasible subsystem of the model (including all updates).
135 //
136 // All input arguments are ensured (by solver.cc) to be valid. Furthermore,
137 // since all parameters are references or functions (which could be a lambda
138 // expression), the implementation should not keep a reference or copy of
139 // them, as they may become invalid reference after the invocation if this
140 // function.
141 //
142 // The parameters `message_cb` and `interrupter` are optional. They are
143 // nullptr when not set.
144 //
145 // When parameter `message_cb` is not null the value of
146 // parameters.enable_output should be ignored the solver should behave as it
147 // is was false (i.e. not print anything).
148 //
149 // When parameter `message_cb` is not null and the underlying solver does not
150 // supports message callbacks, it should ignore it.
151 virtual absl::StatusOr<ComputeInfeasibleSubsystemResultProto>
152 ComputeInfeasibleSubsystem(const SolveParametersProto& parameters,
153 MessageCallback message_cb,
154 const SolveInterrupter* interrupter) = 0;
155};
156
158 public:
161
163
164 // Maps the given factory to the given solver type. Calling this twice will
165 // result in an error, using static initialization is recommended, e.g. see
166 // MATH_OPT_REGISTER_SOLVER defined below.
167 //
168 // Required: factory must be threadsafe.
169 void Register(SolverTypeProto solver_type, SolverInterface::Factory factory);
170
171 // Invokes the factory associated to the solver type with the provided
172 // arguments.
173 absl::StatusOr<std::unique_ptr<SolverInterface>> Create(
174 SolverTypeProto solver_type, const ModelProto& model,
175 const SolverInterface::InitArgs& init_args) const;
176
177 // Whether a solver type is supported.
178 bool IsRegistered(SolverTypeProto solver_type) const;
179
180 // List all supported solver types.
181 std::vector<SolverTypeProto> RegisteredSolvers() const;
182
183 // Returns a human-readable list of supported solver types.
184 std::string RegisteredSolversToString() const;
185
186 private:
187 AllSolversRegistry() = default;
188
189 mutable absl::Mutex mutex_;
190 absl::flat_hash_map<SolverTypeProto, SolverInterface::Factory>
191 registered_solvers_;
192};
193
194// Use to ensure that a solver is registered exactly one time. Invoke in each cc
195// file implementing a SolverInterface. Example use:
196//
197// MATH_OPT_REGISTER_SOLVER(SOLVER_TYPE_GSCIP, GScipSolver::New)
198//
199// Can only be used once per cc file.
200//
201// Arguments:
202// solver_type: A SolverTypeProto proto enum.
203// solver_factory: A SolverInterface::Factory for solver_type.
204#define MATH_OPT_REGISTER_SOLVER(solver_type, solver_factory) \
205 namespace { \
206 const void* const kRegisterSolver ABSL_ATTRIBUTE_UNUSED = [] { \
207 AllSolversRegistry::Instance()->Register(solver_type, solver_factory); \
208 return nullptr; \
209 }(); \
210 } // namespace
211
212} // namespace math_opt
213} // namespace operations_research
214
215#endif // OR_TOOLS_MATH_OPT_CORE_SOLVER_INTERFACE_H_
bool IsRegistered(SolverTypeProto solver_type) const
Whether a solver type is supported.
AllSolversRegistry & operator=(const AllSolversRegistry &)=delete
std::vector< SolverTypeProto > RegisteredSolvers() const
List all supported solver types.
void Register(SolverTypeProto solver_type, SolverInterface::Factory factory)
std::string RegisteredSolversToString() const
Returns a human-readable list of supported solver types.
absl::StatusOr< std::unique_ptr< SolverInterface > > Create(SolverTypeProto solver_type, const ModelProto &model, const SolverInterface::InitArgs &init_args) const
AllSolversRegistry(const AllSolversRegistry &)=delete
SolverInterface(const SolverInterface &)=delete
std::function< void(const std::vector< std::string > &)> MessageCallback
virtual absl::StatusOr< bool > Update(const ModelUpdateProto &model_update)=0
std::function< absl::StatusOr< CallbackResultProto >( const CallbackDataProto &)> Callback
virtual absl::StatusOr< SolveResultProto > Solve(const SolveParametersProto &parameters, const ModelSolveParametersProto &model_parameters, MessageCallback message_cb, const CallbackRegistrationProto &callback_registration, Callback cb, const SolveInterrupter *interrupter)=0
SolverInterface & operator=(const SolverInterface &)=delete
std::function< absl::StatusOr< std::unique_ptr< SolverInterface > >( const ModelProto &model, const InitArgs &init_args)> Factory
virtual absl::StatusOr< ComputeInfeasibleSubsystemResultProto > ComputeInfeasibleSubsystem(const SolveParametersProto &parameters, MessageCallback message_cb, const SolveInterrupter *interrupter)=0
SatParameters parameters
GRBmodel * model
In SWIG mode, we don't want anything besides these top-level includes.
const NonStreamableSolverInitArguments * non_streamable