Google OR-Tools v9.15
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
solver_interface.cc
Go to the documentation of this file.
1// Copyright 2010-2025 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
15
16#include <algorithm>
17#include <memory>
18#include <string>
19#include <utility>
20#include <vector>
21
22#include "absl/base/nullability.h"
23#include "absl/container/flat_hash_map.h"
24#include "absl/container/flat_hash_set.h"
25#include "absl/log/check.h"
26#include "absl/log/log.h"
27#include "absl/status/statusor.h"
28#include "absl/strings/ascii.h"
29#include "absl/strings/match.h"
30#include "absl/strings/str_cat.h"
31#include "absl/strings/str_join.h"
32#include "absl/strings/string_view.h"
33#include "absl/synchronization/mutex.h"
39
40namespace operations_research {
41namespace math_opt {
42namespace {
43
44// Returns the name of the solver type or "unknown(xx)" if the integer does not
45// match a known value.
46std::string SolverTypeName(const SolverTypeProto solver_type) {
47 const std::string name = SolverTypeProto_Name(solver_type);
48 if (!name.empty()) {
49 return name;
50 }
51 return absl::StrCat("unknown(", static_cast<int>(solver_type), ")");
52}
53
54} // namespace
55
56AllSolversRegistry* absl_nullable AllSolversRegistry::temporary_test_instance_ =
57 nullptr;
58
60 static AllSolversRegistry* const instance = new AllSolversRegistry;
61
62 // If a temporary_test_instance_ is set, returns it.
63 if (temporary_test_instance_ != nullptr) {
64 return temporary_test_instance_;
65 }
66
67 return instance;
68}
69
71 const AllSolversRegistry& other,
72 const absl::flat_hash_set<SolverTypeProto>& kept) {
73 // Extract copies of the factories we will keep from other.
74 absl::flat_hash_map<SolverTypeProto, SolverInterface::Factory>
75 kept_registered_solvers;
76 { // Limit the scope of lock.
77 const absl::MutexLock lock(other.mutex_);
78 for (const auto& [solver_type, factory] : other.registered_solvers_) {
79 if (kept.contains(solver_type)) {
80 kept_registered_solvers.try_emplace(solver_type, factory);
81 }
82 }
83 }
84
85 // Find out if all expected solver types were found.
86 for (const SolverTypeProto solver_type : kept) {
87 CHECK(kept_registered_solvers.contains(solver_type))
88 << "Kept solver type " << SolverTypeName(solver_type)
89 << " was not registered in AllSolversRegistry::Instance().";
90 }
91
92 registered_solvers_ = std::move(kept_registered_solvers);
93}
94
95void AllSolversRegistry::SetTemporaryTestInstance(AllSolversRegistry* const
96 absl_nullable temp_instance) {
97 // When we reset we don't test the current value as it is not possible to
98 // override a value anyway.
99 if (temp_instance == nullptr) {
100 CHECK(temporary_test_instance_ != nullptr)
101 << "Can't reset temporary_test_instance_ if not already set!";
102 temporary_test_instance_ = nullptr;
103 return;
104 }
105
106 // At this point temp_instance is not nullptr, set the value of
107 // temporary_test_instance_ iff the current value is null.
108 CHECK(temporary_test_instance_ == nullptr)
109 << "Can't set temporary_test_instance_ to " << temp_instance
110 << ", it is already set to " << temporary_test_instance_ << "!";
111 temporary_test_instance_ = temp_instance;
112}
113
115 SolverInterface::Factory factory) {
116 bool inserted;
117 {
118 const absl::MutexLock lock(mutex_);
119 inserted =
120 registered_solvers_.emplace(solver_type, std::move(factory)).second;
121 }
122 CHECK(inserted) << "Solver type: " << ProtoEnumToString(solver_type)
123 << " already registered.";
124}
125
126absl::StatusOr<std::unique_ptr<SolverInterface>> AllSolversRegistry::Create(
127 SolverTypeProto solver_type, const ModelProto& model,
128 const SolverInterface::InitArgs& init_args) const {
129 const SolverInterface::Factory* factory = nullptr;
130 {
131 const absl::MutexLock lock(mutex_);
132 factory = gtl::FindOrNull(registered_solvers_, solver_type);
133 }
134 if (factory == nullptr) {
136 << "solver type " << SolverTypeName(solver_type)
137 << " is not registered"
138 << ", support for this solver has not been compiled";
139 }
140 return (*factory)(model, init_args);
141}
142
144 const absl::MutexLock lock(mutex_);
145 return registered_solvers_.contains(solver_type);
146}
147
148std::vector<SolverTypeProto> AllSolversRegistry::RegisteredSolvers() const {
149 std::vector<SolverTypeProto> result;
150 {
151 const absl::MutexLock lock(mutex_);
152 for (const auto& kv_pair : registered_solvers_) {
153 result.push_back(kv_pair.first);
154 }
155 }
156 std::sort(result.begin(), result.end());
157 return result;
158}
159
161 std::vector<std::string> solver_names;
162 {
163 const absl::MutexLock lock(mutex_);
164 for (const auto& kv_pair : registered_solvers_) {
165 solver_names.push_back(ProtoEnumToString(kv_pair.first));
166 }
167 }
168 std::sort(solver_names.begin(), solver_names.end());
169 return absl::StrCat("[", absl::StrJoin(solver_names, ","), "]");
170}
171
172} // namespace math_opt
173} // namespace operations_research
bool IsRegistered(SolverTypeProto solver_type) const
std::vector< SolverTypeProto > RegisteredSolvers() const
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
static AllSolversRegistry *absl_nonnull Instance()
AllSolversRegistry(const AllSolversRegistry &)=delete
std::function< absl::StatusOr< std::unique_ptr< SolverInterface > >( const ModelProto &model, const InitArgs &init_args)> Factory
const Collection::value_type::second_type * FindOrNull(const Collection &collection, const typename Collection::value_type::first_type &key)
Definition map_util.h:65
const ::std::string & SolverTypeProto_Name(T value)
OR-Tools root namespace.
std::string ProtoEnumToString(ProtoEnumType enum_value)
Definition proto_utils.h:63
StatusBuilder InvalidArgumentErrorBuilder()