OR-Tools  9.1
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/container/flat_hash_map.h"
23#include "absl/status/status.h"
24#include "absl/status/statusor.h"
25#include "absl/synchronization/mutex.h"
26#include "ortools/math_opt/callback.pb.h"
27#include "ortools/math_opt/model.pb.h"
28#include "ortools/math_opt/model_parameters.pb.h"
29#include "ortools/math_opt/model_update.pb.h"
30#include "ortools/math_opt/parameters.pb.h"
31#include "ortools/math_opt/result.pb.h"
32
33namespace operations_research {
34namespace math_opt {
35
36// Interface implemented by actual solvers.
37//
38// This interface is not meant to be used directly. The actual API is the one of
39// the Solver class. The Solver class validates the models before calling this
40// interface.
41//
42// Implementations of this interface should not have public constructors but
43// instead have a static `New` function with the signature of Factory function
44// as defined below. They should register this factory using the macro
45// MATH_OPT_REGISTER_SOLVER().
47 public:
48 // A callback function (if non null) is a function that validates its input
49 // and its output, and if fails, return a status. The invariant is that the
50 // solver implementation can rely on receiving valid data. The implementation
51 // of this interface must provide valid input (which will be validated) and
52 // in error, it will return a status (without actually calling the callback
53 // function). This is enforced in the solver.cc layer.
54 using Callback = std::function<absl::StatusOr<CallbackResultProto>(
55 const CallbackDataProto&)>;
56
57 // A factory builds a solver based on the input model and parameters.
58 //
59 // Implementation should have a static `New()` function with this signature
60 // and no public constructors.
61 //
62 // The implementation should assume the input ModelProto is valid and is free
63 // to CHECK-fail if this is not the case.
64 using Factory =
65 std::function<absl::StatusOr<std::unique_ptr<SolverInterface>>(
66 const ModelProto& model, const SolverInitializerProto& initializer)>;
67
68 SolverInterface() = default;
71 virtual ~SolverInterface() = default;
72
73 // Solves the current model (included all updates).
74 //
75 // All input arguments are ensured (by solver.cc) to be valid. Furthermore,
76 // since all parameters are references or functions (which could be a lambda
77 // expression), the implementation should not keep a reference or copy of
78 // them, as they may become invalid reference after the invocation if this
79 // function.
80 virtual absl::StatusOr<SolveResultProto> Solve(
81 const SolveParametersProto& parameters,
82 const ModelSolveParametersProto& model_parameters,
83 const CallbackRegistrationProto& callback_registration, Callback cb) = 0;
84
85 // Updates the model to solve.
86 //
87 // The implementation should assume the input ModelUpdate is valid and is free
88 // to assert if this is not the case.
89 virtual absl::Status Update(const ModelUpdateProto& model_update) = 0;
90
91 // Return true if this solver can handle the given update.
92 //
93 // The implementation should assume the input ModelUpdate is valid and is free
94 // to assert if this is not the case.
95 virtual bool CanUpdate(const ModelUpdateProto& model_update) = 0;
96};
97
99 public:
102
104
105 // Maps the given factory to the given solver type. Calling this twice will
106 // result in an error, using static initialization is recommended, e.g. see
107 // MATH_OPT_REGISTER_SOLVER defined below.
108 //
109 // Required: factory must be threadsafe.
110 void Register(SolverType solver_type, SolverInterface::Factory factory);
111
112 // Invokes the factory associated to the solver type with the provided
113 // arguments.
114 absl::StatusOr<std::unique_ptr<SolverInterface>> Create(
115 SolverType solver_type, const ModelProto& model,
116 const SolverInitializerProto& initializer) const;
117
118 // Whether a solver type is supported.
119 bool IsRegistered(SolverType solver_type) const;
120
121 // List all supported solver types.
122 std::vector<SolverType> RegisteredSolvers() const;
123
124 // Returns a human-readable list of supported solver types.
125 std::string RegisteredSolversToString() const;
126
127 private:
128 AllSolversRegistry() = default;
129
130 mutable absl::Mutex mutex_;
131 absl::flat_hash_map<SolverType, SolverInterface::Factory> registered_solvers_;
132};
133
134// Use to ensure that a solver is registered exactly one time. Invoke in each cc
135// file implementing a SolverInterface. Example use:
136//
137// MATH_OPT_REGISTER_SOLVER(SOLVER_TYPE_GSCIP, GScipSolver::New)
138//
139// Can only be used once per cc file.
140//
141// Arguments:
142// solver_type: A SolverType proto enum.
143// solver_factory: A SolverInterface::Factory for solver_type.
144#define MATH_OPT_REGISTER_SOLVER(solver_type, solver_factory) \
145 namespace { \
146 const void* const kRegisterSolver ABSL_ATTRIBUTE_UNUSED = [] { \
147 AllSolversRegistry::Instance()->Register(solver_type, solver_factory); \
148 return nullptr; \
149 }(); \
150 } // namespace
151
152} // namespace math_opt
153} // namespace operations_research
154
155#endif // OR_TOOLS_MATH_OPT_CORE_SOLVER_INTERFACE_H_
AllSolversRegistry(const AllSolversRegistry &)=delete
std::vector< SolverType > RegisteredSolvers() const
AllSolversRegistry & operator=(const AllSolversRegistry &)=delete
bool IsRegistered(SolverType solver_type) const
void Register(SolverType solver_type, SolverInterface::Factory factory)
absl::StatusOr< std::unique_ptr< SolverInterface > > Create(SolverType solver_type, const ModelProto &model, const SolverInitializerProto &initializer) 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, const CallbackRegistrationProto &callback_registration, Callback cb)=0
std::function< absl::StatusOr< CallbackResultProto >(const CallbackDataProto &)> Callback
std::function< absl::StatusOr< std::unique_ptr< SolverInterface > >(const ModelProto &model, const SolverInitializerProto &initializer)> Factory
virtual bool CanUpdate(const ModelUpdateProto &model_update)=0
SolverInterface(const SolverInterface &)=delete
SatParameters parameters
GRBmodel * model
Collection of objects used to extend the Constraint Solver library.