OR-Tools  9.6
objective_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_OBJECTIVE_STORAGE_H_
15 #define OR_TOOLS_MATH_OPT_STORAGE_OBJECTIVE_STORAGE_H_
16 
17 #include <algorithm>
18 #include <utility>
19 #include <vector>
20 
21 #include "absl/container/flat_hash_map.h"
22 #include "absl/container/flat_hash_set.h"
24 #include "ortools/math_opt/model.pb.h"
25 #include "ortools/math_opt/model_update.pb.h"
29 
31 
32 // In memory representation of the objective of an optimization model.
34  public:
35  // Tracks the changes to ObjectiveStorage. Advancing the checkpoint throws
36  // away tracked changes.
37  //
38  // An instance of this class is owned by each update tracker of ModelStorage.
39  struct Diff {
40  explicit Diff(const VariableId variable_checkpoint)
42 
43  VariableId variable_checkpoint{0};
44  bool direction = false;
45  bool offset = false;
46  // Only holds variables before the variable checkpoint.
47  absl::flat_hash_set<VariableId> linear_coefficients;
48 
49  // For each entry, first <= second (the matrix is symmetric).
50  // Only holds entries with both variables before the variable checkpoint.
51  absl::flat_hash_set<std::pair<VariableId, VariableId>>
53  };
54 
55  bool maximize() const { return maximize_; }
56  double offset() const { return offset_; }
57  inline double linear_term(VariableId v) const;
58 
59  const absl::flat_hash_map<VariableId, double>& linear_terms() const {
60  return linear_terms_.terms();
61  }
62  double quadratic_term(const VariableId v1, const VariableId v2) const {
63  return quadratic_terms_.get(v1, v2);
64  }
66  return quadratic_terms_;
67  }
68 
69  template <typename DiffIter>
70  void set_maximize(bool maximize, const iterator_range<DiffIter>& diffs);
71 
72  template <typename DiffIter>
73  void set_offset(double offset, const iterator_range<DiffIter>& diffs);
74 
75  template <typename DiffIter>
76  void set_linear_term(VariableId variable, double value,
77  const iterator_range<DiffIter>& diffs);
78 
79  template <typename DiffIter>
80  void set_quadratic_term(VariableId v1, VariableId v2, double val,
81  const iterator_range<DiffIter>& diffs);
82 
83  template <typename DiffIter>
84  void Clear(const iterator_range<DiffIter>& diffs);
85 
86  // Removes all occurrences of var from the objective.
87  template <typename DiffIter>
88  void DeleteVariable(VariableId variable,
89  const iterator_range<DiffIter>& diffs);
90 
91  ObjectiveProto Proto() const;
92 
94  // Functions for working with Diff
96 
97  // Returns true if there are no changes (tracked changes before the
98  // checkpoint).
99  //
100  // NOTE: when there are new variables with nonzero objective coefficient, the
101  // Diff object can be empty (and diff_is_empty will return true), but Update()
102  // can return a non-empty ObjectiveUpdatesProto. This behavior MAY CHANGE in
103  // the future, so diff_is_empty is true iff Update() returns an empty
104  // ObjectiveUpdatesProto (a more intuitive API, harder to implement
105  // efficiently).
106  inline bool diff_is_empty(const Diff& diff) const;
107 
108  ObjectiveUpdatesProto Update(
109  const Diff& diff,
110  const absl::flat_hash_set<VariableId>& deleted_variables,
111  const std::vector<VariableId>& new_variables) const;
112 
113  // Updates the checkpoint and clears all stored changes in diff.
114  void AdvanceCheckpointInDiff(VariableId variable_checkpoint,
115  Diff& diff) const;
116 
117  private:
118  bool maximize_ = false;
119  double offset_ = 0.0;
120  SparseCoefficientMap linear_terms_;
121  SparseSymmetricMatrix quadratic_terms_;
122 };
123 
125 // Inline function implementation
127 
128 double ObjectiveStorage::linear_term(const VariableId v) const {
129  return linear_terms_.get(v);
130 }
131 
132 template <typename DiffIter>
133 void ObjectiveStorage::set_maximize(const bool maximize,
134  const iterator_range<DiffIter>& diffs) {
135  if (maximize_ == maximize) {
136  return;
137  }
138  maximize_ = maximize;
139  for (ObjectiveStorage::Diff& diff : diffs) {
140  diff.direction = true;
141  }
142 }
143 
144 template <typename DiffIter>
145 void ObjectiveStorage::set_offset(const double offset,
146  const iterator_range<DiffIter>& diffs) {
147  if (offset_ == offset) {
148  return;
149  }
150  offset_ = offset;
151  for (ObjectiveStorage::Diff& diff : diffs) {
152  diff.offset = true;
153  }
154 }
155 
156 template <typename DiffIter>
157 void ObjectiveStorage::set_linear_term(const VariableId variable,
158  const double value,
159  const iterator_range<DiffIter>& diffs) {
160  if (linear_terms_.set(variable, value)) {
161  for (ObjectiveStorage::Diff& diff : diffs) {
162  if (variable < diff.variable_checkpoint) {
163  diff.linear_coefficients.insert(variable);
164  }
165  }
166  }
167 }
168 
169 template <typename DiffIter>
171  const VariableId v1, const VariableId v2, const double val,
172  const iterator_range<DiffIter>& diffs) {
173  if (quadratic_terms_.set(v1, v2, val)) {
174  for (ObjectiveStorage::Diff& diff : diffs) {
175  if (v1 < diff.variable_checkpoint && v2 < diff.variable_checkpoint) {
176  diff.quadratic_coefficients.insert(
177  {std::min(v1, v2), std::max(v1, v2)});
178  }
179  }
180  }
181 }
182 
183 template <typename DiffIter>
185  set_offset(0.0, diffs);
186  for (ObjectiveStorage::Diff& diff : diffs) {
187  for (const auto [var, _] : linear_terms_.terms()) {
188  if (var < diff.variable_checkpoint) {
189  diff.linear_coefficients.insert(var);
190  }
191  }
192  for (const auto [v1, v2, _] : quadratic_terms_.Terms()) {
193  if (v2 < diff.variable_checkpoint) { // v1 <= v2 is implied
194  diff.quadratic_coefficients.insert({v1, v2});
195  }
196  }
197  }
198  linear_terms_.clear();
199  quadratic_terms_.Clear();
200 }
201 
202 template <typename DiffIter>
203 void ObjectiveStorage::DeleteVariable(const VariableId variable,
204  const iterator_range<DiffIter>& diffs) {
205  for (ObjectiveStorage::Diff& diff : diffs) {
206  if (variable >= diff.variable_checkpoint) {
207  continue;
208  }
209  diff.linear_coefficients.erase(variable);
210  for (const VariableId v2 : quadratic_terms_.RelatedVariables(variable)) {
211  if (v2 < diff.variable_checkpoint) {
212  diff.quadratic_coefficients.erase(
213  {std::min(variable, v2), std::max(variable, v2)});
214  }
215  }
216  }
217  linear_terms_.erase(variable);
218  quadratic_terms_.Delete(variable);
219 }
220 
221 bool ObjectiveStorage::diff_is_empty(const Diff& diff) const {
222  return !diff.offset && !diff.direction && diff.linear_coefficients.empty() &&
223  diff.quadratic_coefficients.empty();
224 }
225 
226 } // namespace operations_research::math_opt
227 
228 #endif // OR_TOOLS_MATH_OPT_STORAGE_OBJECTIVE_STORAGE_H_
int64_t max
Definition: alldiff_cst.cc:140
int64_t min
Definition: alldiff_cst.cc:139
const absl::flat_hash_map< VariableId, double > & linear_terms() const
void Clear(const iterator_range< DiffIter > &diffs)
void DeleteVariable(VariableId variable, const iterator_range< DiffIter > &diffs)
double quadratic_term(const VariableId v1, const VariableId v2) const
void set_maximize(bool maximize, const iterator_range< DiffIter > &diffs)
void set_offset(double offset, const iterator_range< DiffIter > &diffs)
void set_linear_term(VariableId variable, double value, const iterator_range< DiffIter > &diffs)
void AdvanceCheckpointInDiff(VariableId variable_checkpoint, Diff &diff) const
void set_quadratic_term(VariableId v1, VariableId v2, double val, const iterator_range< DiffIter > &diffs)
ObjectiveUpdatesProto Update(const Diff &diff, const absl::flat_hash_set< VariableId > &deleted_variables, const std::vector< VariableId > &new_variables) const
const SparseSymmetricMatrix & quadratic_terms() const
const absl::flat_hash_map< VariableId, double > & terms() const
bool set(const VariableId id, const double coeff)
double get(VariableId first, VariableId second) const
std::vector< VariableId > RelatedVariables(VariableId variable) const
bool set(VariableId first, VariableId second, double value)
std::vector< std::pair< VariableId, double > > Terms(VariableId variable) const
int64_t value
IntVar * var
Definition: expr_array.cc:1874
absl::flat_hash_set< std::pair< VariableId, VariableId > > quadratic_coefficients
Diff(const VariableId variable_checkpoint)
absl::flat_hash_set< VariableId > linear_coefficients