Google OR-Tools v9.15
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
variable_storage.h
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
14#ifndef ORTOOLS_MATH_OPT_STORAGE_VARIABLE_STORAGE_H_
15#define ORTOOLS_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"
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
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.
63 // Variables created at or after the checkpoint that have not been deleted.
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>
82 const iterator_range<DiffIter>& diffs);
83
84 template <typename DiffIter>
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
163double VariableStorage::lower_bound(const VariableId id) const {
164 return variables_.at(id).lower_bound;
165}
166
168 return variables_.at(id).upper_bound;
169}
170
172 return variables_.at(id).is_integer;
173}
174
175const std::string& VariableStorage::name(const VariableId id) const {
176 return variables_.at(id).name;
177}
178
179template <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
194template <typename DiffIter>
195void VariableStorage::set_upper_bound(VariableId id, double upper_bound,
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
209template <typename DiffIter>
210void 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
224template <typename DiffIter>
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
239int64_t VariableStorage::size() const { return variables_.size(); }
240
241VariableId VariableStorage::next_id() const { return next_variable_id_; }
242
244 next_variable_id_ = std::max(minimum, next_variable_id_);
246
248 return variables_.contains(id);
249}
250
251bool 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();
256
257} // namespace operations_research::math_opt
258
259#endif // ORTOOLS_MATH_OPT_STORAGE_VARIABLE_STORAGE_H_
std::vector< VariableId > Variables() const
void set_integer(VariableId id, bool is_integer, const iterator_range< DiffIter > &diffs)
std::vector< VariableId > SortedVariables() const
void set_lower_bound(VariableId id, double lower_bound, const iterator_range< DiffIter > &diffs)
std::vector< VariableId > VariablesFrom(VariableId start) const
void set_upper_bound(VariableId id, double upper_bound, const iterator_range< DiffIter > &diffs)
VariableId Add(double lower_bound, double upper_bound, bool is_integer, absl::string_view name)
void Delete(VariableId id, const iterator_range< DiffIter > &diffs)
const std::string & name(VariableId id) const
UpdateResult Update(const Diff &diff) const
ElementId< ElementType::kVariable > VariableId
Definition elements.h:80
google::protobuf::RepeatedField< int64_t > deleted