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