model.h
Go to the documentation of this file.
1 // Copyright 2010-2018 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 <functional>
19 #include <map>
20 #include <memory>
21 #include <vector>
22 
23 #include "ortools/base/logging.h"
24 #include "ortools/base/macros.h"
25 #include "ortools/base/map_util.h"
26 #include "ortools/base/typeid.h"
27 
28 namespace operations_research {
29 namespace sat {
30 
31 // Class that owns everything related to a particular optimization model.
32 //
33 // This class is actually a fully generic wrapper that can hold any type of
34 // constraints, watchers, solvers and provide a mecanism to wire them together.
35 class Model {
36  public:
37  Model() {}
38 
39  // This allows to have a nicer API on the client side, and it allows both of
40  // these forms:
41  // - ConstraintCreationFunction(contraint_args, &model);
42  // - model.Add(ConstraintCreationFunction(contraint_args));
43  //
44  // The second form is a bit nicer for the client and it also allows to store
45  // constraints and add them later. However, the function creating the
46  // constraint is slighly more involved:
47  //
48  // std::function<void(Model*)> ConstraintCreationFunction(contraint_args) {
49  // return [=] (Model* model) {
50  // ... the same code ...
51  // };
52  // }
53  //
54  // We also have a templated return value for the functions that need it like
55  // const BooleanVariable b = model.Add(NewBooleanVariable());
56  // const IntegerVariable i = model.Add(NewWeightedSum(weigths, variables));
57  template <typename T>
58  T Add(std::function<T(Model*)> f) {
59  return f(this);
60  }
61 
62  // Similar to Add() but this is const.
63  template <typename T>
64  T Get(std::function<T(const Model&)> f) const {
65  return f(*this);
66  }
67 
68  // Returns an object of type T that is unique to this model (like a "local"
69  // singleton). This returns an already created instance or create a new one if
70  // needed using the T(Model* model) constructor if it exist or T() otherwise.
71  //
72  // This works a bit like in a dependency injection framework and allows to
73  // really easily wire all the classes that make up a solver together. For
74  // instance a constraint can depends on the LiteralTrail, or the IntegerTrail
75  // or both, it can depend on a Watcher class to register itself in order to
76  // be called when needed and so on.
77  //
78  // IMPORTANT: the Model* constructors function shouldn't form a cycle between
79  // each other, otherwise this will crash the program.
80  template <typename T>
81  T* GetOrCreate() {
82  const size_t type_id = gtl::FastTypeId<T>();
83  if (!gtl::ContainsKey(singletons_, type_id)) {
84  // TODO(user): directly store std::unique_ptr<> in singletons_?
85  T* new_t = MyNew<T>(0);
86  singletons_[type_id] = new_t;
87  TakeOwnership(new_t);
88  return new_t;
89  }
90  return static_cast<T*>(gtl::FindOrDie(singletons_, type_id));
91  }
92 
93  // Likes GetOrCreate() but do not create the object if it is non-existing.
94  // This returns a const version of the object.
95  template <typename T>
96  const T* Get() const {
97  return static_cast<const T*>(
98  gtl::FindWithDefault(singletons_, gtl::FastTypeId<T>(), nullptr));
99  }
100 
101  // Same as Get(), but returns a mutable version of the object.
102  template <typename T>
103  T* Mutable() const {
104  return static_cast<T*>(
105  gtl::FindWithDefault(singletons_, gtl::FastTypeId<T>(), nullptr));
106  }
107 
108  // Gives ownership of a pointer to this model.
109  // It will be destroyed when the model is.
110  template <typename T>
111  void TakeOwnership(T* t) {
112  cleanup_list_.emplace_back(new Delete<T>(t));
113  }
114 
115  // This returns a non-singleton object owned by the model and created with the
116  // T(Model* model) constructor if it exist or the T() constructor otherwise.
117  // It is just a shortcut to new + TakeOwnership().
118  template <typename T>
119  T* Create() {
120  T* new_t = MyNew<T>(0);
121  TakeOwnership(new_t);
122  return new_t;
123  }
124 
125  // Register a non-owned class that will be "singleton" in the model.
126  // It is an error to call this on an already registered class.
127  template <typename T>
128  void Register(T* non_owned_class) {
129  const size_t type_id = gtl::FastTypeId<T>();
130  CHECK(!gtl::ContainsKey(singletons_, type_id));
131  singletons_[type_id] = non_owned_class;
132  }
133 
134  private:
135  // We want to call the constructor T(model*) if it exists or just T() if
136  // it doesn't. For this we use some template "magic":
137  // - The first MyNew() will only be defined if the type in decltype() exist.
138  // - The second MyNew() will always be defined, but because of the ellipsis
139  // it has lower priority that the first one.
140  template <typename T>
141  decltype(T(static_cast<Model*>(nullptr)))* MyNew(int) {
142  return new T(this);
143  }
144  template <typename T>
145  T* MyNew(...) {
146  return new T();
147  }
148 
149  // Map of FastTypeId<T> to a "singleton" of type T.
150  std::map</*typeid*/ size_t, void*> singletons_;
151 
152  struct DeleteInterface {
153  virtual ~DeleteInterface() = default;
154  };
155  template <typename T>
156  class Delete : public DeleteInterface {
157  public:
158  explicit Delete(T* t) : to_delete_(t) {}
159  ~Delete() override = default;
160 
161  private:
162  std::unique_ptr<T> to_delete_;
163  };
164 
165  // The list of items to delete.
166  //
167  // TODO(user): I don't think we need the two layers of unique_ptr, but we
168  // don't care too much about efficiency here and this was easier to get
169  // working.
170  std::vector<std::unique_ptr<DeleteInterface>> cleanup_list_;
171 
172  DISALLOW_COPY_AND_ASSIGN(Model);
173 };
174 
175 } // namespace sat
176 } // namespace operations_research
177 
178 #endif // OR_TOOLS_SAT_MODEL_H_
T Get(std::function< T(const Model &)> f) const
Similar to Add() but this is const.
Definition: model.h:64
void TakeOwnership(T *t)
Gives ownership of a pointer to this model.
Definition: model.h:111
void Register(T *non_owned_class)
Register a non-owned class that will be "singleton" in the model.
Definition: model.h:128
T * Create()
This returns a non-singleton object owned by the model and created with the T(Model* model) construct...
Definition: model.h:119
Class that owns everything related to a particular optimization model.
Definition: model.h:35
const T * Get() const
Likes GetOrCreate() but do not create the object if it is non-existing.
Definition: model.h:96
T * GetOrCreate()
Returns an object of type T that is unique to this model (like a "local" singleton).
Definition: model.h:81
T Add(std::function< T(Model *)> f)
This allows to have a nicer API on the client side, and it allows both of these forms:
Definition: model.h:58
T * Mutable() const
Same as Get(), but returns a mutable version of the object.
Definition: model.h:103
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in c...
Definition: cp_model.h:48