C++ Reference

C++ Reference: CP-SAT

model.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_SAT_MODEL_H_
15#define OR_TOOLS_SAT_MODEL_H_
16
17#include <cstddef>
18#include <cstdio>
19#include <ctime>
20#include <functional>
21#include <memory>
22#include <new>
23#include <string>
24#include <vector>
25
26#include "absl/container/flat_hash_map.h"
27#include "absl/meta/type_traits.h"
28#include "ortools/base/logging.h"
29#include "ortools/base/macros.h"
30#include "ortools/base/map_util.h"
31#include "ortools/base/typeid.h"
32
33namespace operations_research {
34namespace sat {
35
42class Model {
43 public:
44 Model() {}
45
47 // The order of deletion seems to be platform dependent.
48 // We force a reverse order on the cleanup vector.
49 for (int i = cleanup_list_.size() - 1; i >= 0; --i) {
50 cleanup_list_[i].reset();
51 }
52 }
53
58 explicit Model(std::string name) : name_(name) {}
59
84 template <typename T>
85 T Add(std::function<T(Model*)> f) {
86 return f(this);
87 }
88
90 template <typename T>
91 T Get(std::function<T(const Model&)> f) const {
92 return f(*this);
93 }
94
109 template <typename T>
111 const size_t type_id = gtl::FastTypeId<T>();
112 auto find = singletons_.find(type_id);
113 if (find != singletons_.end()) {
114 return static_cast<T*>(find->second);
115 }
116
117 // New element.
118 // TODO(user): directly store std::unique_ptr<> in singletons_?
119 T* new_t = MyNew<T>(0);
120 singletons_[type_id] = new_t;
121 TakeOwnership(new_t);
122 return new_t;
123 }
124
130 template <typename T>
131 const T* Get() const {
132 return static_cast<const T*>(
133 gtl::FindWithDefault(singletons_, gtl::FastTypeId<T>(), nullptr));
134 }
135
139 template <typename T>
140 T* Mutable() const {
141 return static_cast<T*>(
142 gtl::FindWithDefault(singletons_, gtl::FastTypeId<T>(), nullptr));
143 }
144
150 template <typename T>
151 void TakeOwnership(T* t) {
152 cleanup_list_.emplace_back(new Delete<T>(t));
153 }
154
160 template <typename T>
161 T* Create() {
162 T* new_t = MyNew<T>(0);
163 TakeOwnership(new_t);
164 return new_t;
165 }
166
172 template <typename T>
173 void Register(T* non_owned_class) {
174 const size_t type_id = gtl::FastTypeId<T>();
175 CHECK(!singletons_.contains(type_id));
176 singletons_[type_id] = non_owned_class;
177 }
178
179 const std::string& Name() const { return name_; }
180
181 private:
182 // We want to call the constructor T(model*) if it exists or just T() if
183 // it doesn't. For this we use some template "magic":
184 // - The first MyNew() will only be defined if the type in decltype() exist.
185 // - The second MyNew() will always be defined, but because of the ellipsis
186 // it has lower priority that the first one.
187 template <typename T>
188 decltype(T(static_cast<Model*>(nullptr)))* MyNew(int) {
189 return new T(this);
190 }
191 template <typename T>
192 T* MyNew(...) {
193 return new T();
194 }
195
196 const std::string name_;
197
198 // Map of FastTypeId<T> to a "singleton" of type T.
199 absl::flat_hash_map</*typeid*/ size_t, void*> singletons_;
200
201 struct DeleteInterface {
202 virtual ~DeleteInterface() = default;
203 };
204 template <typename T>
205 class Delete : public DeleteInterface {
206 public:
207 explicit Delete(T* t) : to_delete_(t) {}
208 ~Delete() override = default;
209
210 private:
211 std::unique_ptr<T> to_delete_;
212 };
213
214 // The list of items to delete.
215 //
216 // TODO(user): I don't think we need the two layers of unique_ptr, but we
217 // don't care too much about efficiency here and this was easier to get
218 // working.
219 std::vector<std::unique_ptr<DeleteInterface>> cleanup_list_;
220
221 DISALLOW_COPY_AND_ASSIGN(Model);
222};
223
224} // namespace sat
225} // namespace operations_research
226
227#endif // OR_TOOLS_SAT_MODEL_H_
Class that owns everything related to a particular optimization model.
Definition: model.h:42
T * Create()
This returns a non-singleton object owned by the model and created with the T(Model* model) construct...
Definition: model.h:161
T Get(std::function< T(const Model &)> f) const
Similar to Add() but this is const.
Definition: model.h:91
T Add(std::function< T(Model *)> f)
This makes it possible to have a nicer API on the client side, and it allows both of these forms:
Definition: model.h:85
void Register(T *non_owned_class)
Register a non-owned class that will be "singleton" in the model.
Definition: model.h:173
const std::string & Name() const
Definition: model.h:179
const T * Get() const
Likes GetOrCreate() but do not create the object if it is non-existing.
Definition: model.h:131
Model(std::string name)
When there is more than one model in an application, it makes sense to name them for debugging or log...
Definition: model.h:58
T * Mutable() const
Same as Get(), but returns a mutable version of the object.
Definition: model.h:140
void TakeOwnership(T *t)
Gives ownership of a pointer to this model.
Definition: model.h:151
T * GetOrCreate()
Returns an object of type T that is unique to this model (like a "local" singleton).
Definition: model.h:110