C++ Reference

C++ Reference: CP-SAT

model.h
Go to the documentation of this file.
1 // Copyright 2010-2022 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 <map>
22 #include <memory>
23 #include <new>
24 #include <string>
25 #include <vector>
26 
27 #include "absl/container/flat_hash_map.h"
28 #include "absl/meta/type_traits.h"
29 #include "ortools/base/logging.h"
30 #include "ortools/base/macros.h"
31 #include "ortools/base/typeid.h"
32 
33 namespace operations_research {
34 namespace sat {
35 
42 class Model {
43  public:
44  Model() {}
45 
46  ~Model() {
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>
110  T* GetOrCreate() {
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  const auto& it = singletons_.find(gtl::FastTypeId<T>());
133  return it != singletons_.end() ? static_cast<const T*>(it->second)
134  : nullptr;
135  }
136 
140  template <typename T>
141  T* Mutable() const {
142  const auto& it = singletons_.find(gtl::FastTypeId<T>());
143  return it != singletons_.end() ? static_cast<T*>(it->second) : nullptr;
144  }
145 
151  template <typename T>
152  T* TakeOwnership(T* t) {
153  cleanup_list_.emplace_back(new Delete<T>(t));
154  return t;
155  }
156 
162  template <typename T>
163  T* Create() {
164  T* new_t = MyNew<T>(0);
165  TakeOwnership(new_t);
166  return new_t;
167  }
168 
174  template <typename T>
175  void Register(T* non_owned_class) {
176  const size_t type_id = gtl::FastTypeId<T>();
177  CHECK(!singletons_.contains(type_id));
178  singletons_[type_id] = non_owned_class;
179  }
180 
181  const std::string& Name() const { return name_; }
182 
183  private:
184  // We want to call the constructor T(model*) if it exists or just T() if
185  // it doesn't. For this we use some template "magic":
186  // - The first MyNew() will only be defined if the type in decltype() exist.
187  // - The second MyNew() will always be defined, but because of the ellipsis
188  // it has lower priority that the first one.
189  template <typename T>
190  decltype(T(static_cast<Model*>(nullptr)))* MyNew(int) {
191  return new T(this);
192  }
193  template <typename T>
194  T* MyNew(...) {
195  return new T();
196  }
197 
198  const std::string name_;
199 
200  // Map of FastTypeId<T> to a "singleton" of type T.
201  absl::flat_hash_map</*typeid*/ size_t, void*> singletons_;
202 
203  struct DeleteInterface {
204  virtual ~DeleteInterface() = default;
205  };
206  template <typename T>
207  class Delete : public DeleteInterface {
208  public:
209  explicit Delete(T* t) : to_delete_(t) {}
210  ~Delete() override = default;
211 
212  private:
213  std::unique_ptr<T> to_delete_;
214  };
215 
216  // The list of items to delete.
217  //
218  // TODO(user): I don't think we need the two layers of unique_ptr, but we
219  // don't care too much about efficiency here and this was easier to get
220  // working.
221  std::vector<std::unique_ptr<DeleteInterface>> cleanup_list_;
222 
223  DISALLOW_COPY_AND_ASSIGN(Model);
224 };
225 
226 } // namespace sat
227 } // namespace operations_research
228 
229 #endif // OR_TOOLS_SAT_MODEL_H_
Class that owns everything related to a particular optimization model.
Definition: model.h:42
const std::string & Name() const
Definition: model.h:181
T Get(std::function< T(const Model &)> f) const
Similar to Add() but this is const.
Definition: model.h:91
T * Create()
This returns a non-singleton object owned by the model and created with the T(Model* model) construct...
Definition: model.h:163
const T * Get() const
Likes GetOrCreate() but do not create the object if it is non-existing.
Definition: model.h:131
T * TakeOwnership(T *t)
Gives ownership of a pointer to this model.
Definition: model.h:152
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:175
T * GetOrCreate()
Returns an object of type T that is unique to this model (like a "local" singleton).
Definition: model.h:110
T * Mutable() const
Same as Get(), but returns a mutable version of the object.
Definition: model.h:141
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