Google OR-Tools v9.11
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-2024 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
163double VariableStorage::lower_bound(const VariableId id) const {
164 return variables_.at(id).lower_bound;
165}
166
167double VariableStorage::upper_bound(const VariableId id) const {
168 return variables_.at(id).upper_bound;
169}
170
171bool VariableStorage::is_integer(VariableId id) const {
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>
180void VariableStorage::set_lower_bound(VariableId id, double lower_bound,
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>
225void 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
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
247bool VariableStorage::contains(const VariableId id) const {
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 // OR_TOOLS_MATH_OPT_STORAGE_VARIABLE_STORAGE_H_
bool contains(VariableId id) const
Returns true if this id has been created and not yet deleted.
VariablesProto Proto() const
An equivalent proto of this.
std::vector< VariableId > Variables() const
The VariableIds in use (not deleted), order not defined.
void AdvanceCheckpointInDiff(Diff &diff) const
Updates the checkpoint and clears all stored changes in diff.
void set_integer(VariableId id, bool is_integer, const iterator_range< DiffIter > &diffs)
void ensure_next_id_at_least(VariableId minimum)
Sets the next variable id to be the maximum of next_id() and minimum.
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
CpModelProto proto
The output proto.
const std::string name
A name for logging purposes.
double upper_bound
double lower_bound
An object oriented wrapper for quadratic constraints in ModelStorage.
Definition gurobi_isv.cc:28
int64_t start
google::protobuf::RepeatedField< int64_t > deleted
Variables before the checkpoint that have been deleted.
VariablesProto creates
Variables created at or after the checkpoint that have not been deleted.
VariableUpdatesProto updates
Variables before the checkpoint that have been modified and not deleted.