OR-Tools  9.2
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 
33 namespace operations_research {
34 namespace 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;
69  SolverInterface(const SolverInterface&) = delete;
70  SolverInterface& operator=(const SolverInterface&) = delete;
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:
100  AllSolversRegistry(const AllSolversRegistry&) = delete;
102 
103  static AllSolversRegistry* Instance();
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_
virtual absl::StatusOr< SolveResultProto > Solve(const SolveParametersProto &parameters, const ModelSolveParametersProto &model_parameters, const CallbackRegistrationProto &callback_registration, Callback cb)=0
bool IsRegistered(SolverType solver_type) const
GRBmodel * model
AllSolversRegistry & operator=(const AllSolversRegistry &)=delete
void Register(SolverType solver_type, SolverInterface::Factory factory)
virtual absl::Status Update(const ModelUpdateProto &model_update)=0
virtual bool CanUpdate(const ModelUpdateProto &model_update)=0
absl::StatusOr< std::unique_ptr< SolverInterface > > Create(SolverType solver_type, const ModelProto &model, const SolverInitializerProto &initializer) const
std::function< absl::StatusOr< CallbackResultProto >(const CallbackDataProto &)> Callback
SolverInterface & operator=(const SolverInterface &)=delete
Collection of objects used to extend the Constraint Solver library.
std::function< absl::StatusOr< std::unique_ptr< SolverInterface > >(const ModelProto &model, const SolverInitializerProto &initializer)> Factory
SatParameters parameters
std::vector< SolverType > RegisteredSolvers() const