OR-Tools  9.6
variable_storage.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_MATH_OPT_STORAGE_VARIABLE_STORAGE_H_
15 #define OR_TOOLS_MATH_OPT_STORAGE_VARIABLE_STORAGE_H_
16 
17 #include <algorithm>
18 #include <cstdint>
19 #include <limits>
20 #include <string>
21 #include <vector>
22 
23 #include "absl/container/flat_hash_map.h"
24 #include "absl/container/flat_hash_set.h"
25 #include "absl/strings/string_view.h"
27 #include "ortools/math_opt/model.pb.h"
28 #include "ortools/math_opt/model_update.pb.h"
31 
33 
34 // The in memory representation of the variables of an optimization model.
35 //
36 // The setter functions all accept a `DiffIter`, which must be an iterator over
37 // non-const references to VariableStorage::Diff. These
38 // functions will modify the VariableStorage::Diff objects.
40  public:
41  // Tracks a "checkpoint" and the changes to variables that are before the
42  // checkpoint. Advancing the checkpoint throws away tracked changes.
43  //
44  // An instance of this class is owned by each update tracker of ModelStorage.
45  struct Diff {
46  explicit Diff(const VariableStorage& storage)
47  : checkpoint(storage.next_id()) {}
48 
49  VariableId checkpoint = VariableId(0);
50  absl::flat_hash_set<VariableId> deleted;
51  absl::flat_hash_set<VariableId> lower_bounds;
52  absl::flat_hash_set<VariableId> upper_bounds;
53  absl::flat_hash_set<VariableId> integer;
54  };
55 
56  // A description of the changes to the variables of the model with respect to
57  // a known checkpoint.
58  struct UpdateResult {
59  // Variables before the checkpoint that have been deleted.
60  google::protobuf::RepeatedField<int64_t> deleted;
61  // Variables before the checkpoint that have been modified and not deleted.
62  VariableUpdatesProto updates;
63  // Variables created at or after the checkpoint that have not been deleted.
64  VariablesProto creates;
65  };
66 
67  // Adds a variable to the model and returns its id.
68  //
69  // The returned ids begin at zero and strictly increase (in particular, if
70  // ensure_next_id_at_least() is not used, they will be consecutive). Deleted
71  // ids are NOT reused.
72  VariableId Add(double lower_bound, double upper_bound, bool is_integer,
73  absl::string_view name);
74 
75  inline double lower_bound(VariableId id) const;
76  inline double upper_bound(VariableId id) const;
77  inline bool is_integer(VariableId id) const;
78  inline const std::string& name(VariableId id) const;
79 
80  template <typename DiffIter>
81  void set_lower_bound(VariableId id, double lower_bound,
82  const iterator_range<DiffIter>& diffs);
83 
84  template <typename DiffIter>
85  void set_upper_bound(VariableId id, double upper_bound,
86  const iterator_range<DiffIter>& diffs);
87 
88  template <typename DiffIter>
89  void set_integer(VariableId id, bool is_integer,
90  const iterator_range<DiffIter>& diffs);
91 
92  // Removes a variable from the model.
93  //
94  // It is an error to use a deleted variable id as input to any subsequent
95  // function calls on this.
96  template <typename DiffIter>
97  void Delete(VariableId id, const iterator_range<DiffIter>& diffs);
98 
99  // The number of variables in the model.
100  //
101  // Equal to the number of variables created minus the number of variables
102  // deleted.
103  inline int64_t size() const;
104 
105  // The returned id of the next call to AddVariable.
106  //
107  // Equal to the number of variables created.
108  inline VariableId next_id() const;
109 
110  // Sets the next variable id to be the maximum of next_id() and `minimum`.
111  inline void ensure_next_id_at_least(VariableId minimum);
112 
113  // Returns true if this id has been created and not yet deleted.
114  inline bool contains(VariableId id) const;
115 
116  // The VariableIds in use (not deleted), order not defined.
117  std::vector<VariableId> Variables() const;
118 
119  // Returns a sorted vector of all existing (not deleted) variables in the
120  // model.
121  //
122  // Runs in O(n log(n)), where n is the number of variables returned.
123  std::vector<VariableId> SortedVariables() const;
124 
125  // An equivalent proto of `this`.
126  VariablesProto Proto() const;
127 
129  // Functions for working with Diff
131 
132  // Returns true if there are no changes (tracked changes before the checkpoint
133  // or new constraints after the checkpoint).
134  inline bool diff_is_empty(const Diff& diff) const;
135 
136  UpdateResult Update(const Diff& diff) const;
137 
138  // Updates the checkpoint and clears all stored changes in diff.
139  void AdvanceCheckpointInDiff(Diff& diff) const;
140 
141  // Returns the variables in the model starting with start (inclusive) and
142  // larger in order. Runs in O(next_id() - start).
143  std::vector<VariableId> VariablesFrom(VariableId start) const;
144 
145  private:
146  struct VariableData {
147  double lower_bound = -std::numeric_limits<double>::infinity();
148  double upper_bound = std::numeric_limits<double>::infinity();
149  bool is_integer = false;
150  std::string name = "";
151  };
152 
153  void AppendVariable(VariableId variable, VariablesProto* proto) const;
154 
155  VariableId next_variable_id_ = VariableId(0);
156  absl::flat_hash_map<VariableId, VariableData> variables_;
157 };
158 
160 // Inline functions
162 
163 double VariableStorage::lower_bound(const VariableId id) const {
164  return variables_.at(id).lower_bound;
165 }
166 
167 double VariableStorage::upper_bound(const VariableId id) const {
168  return variables_.at(id).upper_bound;
169 }
170 
171 bool VariableStorage::is_integer(VariableId id) const {
172  return variables_.at(id).is_integer;
173 }
174 
175 const std::string& VariableStorage::name(const VariableId id) const {
176  return variables_.at(id).name;
177 }
178 
179 template <typename DiffIter>
181  const iterator_range<DiffIter>& diffs) {
182  VariableData& data = variables_.at(id);
183  if (data.lower_bound == lower_bound) {
184  return;
185  }
186  data.lower_bound = lower_bound;
187  for (Diff& diff : diffs) {
188  if (id < diff.checkpoint) {
189  diff.lower_bounds.insert(id);
190  }
191  }
192 }
193 
194 template <typename DiffIter>
196  const iterator_range<DiffIter>& diffs) {
197  VariableData& data = variables_.at(id);
198  if (data.upper_bound == upper_bound) {
199  return;
200  }
201  data.upper_bound = upper_bound;
202  for (Diff& diff : diffs) {
203  if (id < diff.checkpoint) {
204  diff.upper_bounds.insert(id);
205  }
206  }
207 }
208 
209 template <typename DiffIter>
210 void VariableStorage::set_integer(VariableId id, bool is_integer,
211  const iterator_range<DiffIter>& diffs) {
212  VariableData& data = variables_.at(id);
213  if (data.is_integer == is_integer) {
214  return;
215  }
216  data.is_integer = is_integer;
217  for (Diff& diff : diffs) {
218  if (id < diff.checkpoint) {
219  diff.integer.insert(id);
220  }
221  }
222 }
223 
224 template <typename DiffIter>
225 void VariableStorage::Delete(VariableId id,
226  const iterator_range<DiffIter>& diffs) {
227  for (Diff& diff : diffs) {
228  if (id >= diff.checkpoint) {
229  continue;
230  }
231  diff.deleted.insert(id);
232  diff.lower_bounds.erase(id);
233  diff.upper_bounds.erase(id);
234  diff.integer.erase(id);
235  }
236  variables_.erase(id);
237 }
238 
239 int64_t VariableStorage::size() const { return variables_.size(); }
240 
241 VariableId VariableStorage::next_id() const { return next_variable_id_; }
242 
244  next_variable_id_ = std::max(minimum, next_variable_id_);
245 }
246 
247 bool VariableStorage::contains(const VariableId id) const {
248  return variables_.contains(id);
249 }
250 
251 bool VariableStorage::diff_is_empty(const Diff& diff) const {
252  return next_variable_id_ <= diff.checkpoint && diff.deleted.empty() &&
253  diff.lower_bounds.empty() && diff.upper_bounds.empty() &&
254  diff.integer.empty();
255 }
256 
257 } // namespace operations_research::math_opt
258 
259 #endif // OR_TOOLS_MATH_OPT_STORAGE_VARIABLE_STORAGE_H_
int64_t max
Definition: alldiff_cst.cc:140
void set_integer(VariableId id, bool is_integer, const iterator_range< DiffIter > &diffs)
void set_lower_bound(VariableId id, double lower_bound, const iterator_range< DiffIter > &diffs)
void Delete(VariableId id, const iterator_range< DiffIter > &diffs)
std::vector< VariableId > SortedVariables() const
void set_upper_bound(VariableId id, double upper_bound, const iterator_range< DiffIter > &diffs)
std::vector< VariableId > VariablesFrom(VariableId start) const
VariableId Add(double lower_bound, double upper_bound, bool is_integer, absl::string_view name)
const std::string & name(VariableId id) const
std::vector< VariableId > Variables() const
UpdateResult Update(const Diff &diff) const
CpModelProto proto
IntVar * upper_bound
Definition: routing.cc:1087
IntVar * lower_bound
Definition: routing.cc:1086
int64_t start
absl::flat_hash_set< VariableId > lower_bounds
absl::flat_hash_set< VariableId > upper_bounds
google::protobuf::RepeatedField< int64_t > deleted