Google OR-Tools v9.14
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
elemental_differencer.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 OR_TOOLS_MATH_OPT_ELEMENTAL_ELEMENTAL_DIFFERENCER_H_
15#define OR_TOOLS_MATH_OPT_ELEMENTAL_ELEMENTAL_DIFFERENCER_H_
16
17#include <array>
18#include <cstdint>
19#include <string>
20#include <vector>
21
22#include "absl/container/flat_hash_set.h"
28
30
31// Returns the elements in both first and second.
32template <typename T>
33absl::flat_hash_set<T> IntersectSets(const absl::flat_hash_set<T>& first,
34 const absl::flat_hash_set<T>& second);
35
36// The elements in the set first, but not in second, and the elements in the set
37// second, but not in first.
38template <typename T>
40 absl::flat_hash_set<T> only_in_first;
41 absl::flat_hash_set<T> only_in_second;
42
43 explicit SymmetricDifference() = default;
44 explicit SymmetricDifference(const absl::flat_hash_set<T>& first,
45 const absl::flat_hash_set<T>& second);
46
47 bool Empty() const { return only_in_first.empty() && only_in_second.empty(); }
48};
49
50// TODO(b/368421402): many features are missing here, e.g. floating point
51// tolerance, allowing variables to be permuted.
53 bool check_names = true;
54 bool check_next_id = true;
55};
56
57// Holds the difference between the model from two `Elemental`s. Typically used
58// to check if two Elemental objects are the same, and provide a nice
59// description of how they differ if they are not the same.
60//
61// Note that:
62// * This is an entirely separate concept from the Diff object held by an
63// an Elemental, which tracks changes to an Elemental from a point in time.
64// The similarity in names is unfortunate and confusing.
65// * This class only tracks differences between the models, it ignores any Diff
66// objects either Elemental contains.
68 public:
69 // The difference for an `ElementType`.
71 // Element ids in one elemental but not in the other.
73
74 // Element ids in both elementals where the element names disagree.
75 absl::flat_hash_set<int64_t> different_names;
76
77 // The value of next_id for this ElementType differs.
78 bool next_id_different = false;
79
80 // Indicates there are no differences for this ElementType.
81 bool Empty() const;
82 };
83
84 // The difference for an attribute. E.g. for the attribute
85 // DoubleAttr1::kVarLb, we would take `AttrType` DoubleAttr1.
86 template <typename AttrType>
89
90 // The keys with non-default value for this attribute in one Elemental but
91 // not the other.
93
94 // The keys where the attribute has a different non-default value in each
95 // Elemental.
96 absl::flat_hash_set<Key> different_values;
97
98 // Returns every key in `keys` or `different_values` (the keys that the
99 // attribute is different on).
100 std::vector<Key> AllKeysSorted() const;
101
102 // Indicates that there are no differences for this attribute.
103 bool Empty() const;
104 };
105
106 // Returns the difference between two Elementals.
108 const Elemental& first, const Elemental& second,
109 const ElementalDifferenceOptions& options = {});
110 explicit ElementalDifference() = default;
111
112 // Returns a string describing the difference between two models.
113 static std::string DescribeDifference(
114 const Elemental& first, const Elemental& second,
115 const ElementalDifferenceOptions& options = {});
116
117 // Returns a string describing `difference`, using data from `first` and
118 // `second` to make the output more human readable (e.g. show element names),
119 // or CHECK fails on bad input (see below).
120 //
121 // Advanced use, generally prefer `DescribeDifference(const Elemental&,
122 // const Elemental&, const ElementalDifferenceOptions&)` instead, which cannot
123 // CHECK fail. Useful if you want to compute the difference and do some
124 // logical operations before (perhaps conditionally) converting the difference
125 // to a string.
126 //
127 // This function can CHECK fail if `difference` claims that `first` or
128 // `second` contains an element which is missing. A sufficient condition to
129 // ensure that this function will NOT CHECK is to invoke it as
130 // Describe(first, second, Create(first, second))
131 // to ensure that the models are correct and not modified between Create() and
132 // Describe().
133 static std::string Describe(const Elemental& first, const Elemental& second,
134 const ElementalDifference& difference);
135
137 const ElementType e) const {
138 return elements_[static_cast<int>(e)];
139 }
140
142 return elements_[static_cast<int>(e)];
143 }
144
145 template <typename AttrType>
146 const AttributeDifference<AttrType>& attr_difference(const AttrType a) const {
147 return attrs_[a];
148 }
149
150 template <typename AttrType>
152 return attrs_[a];
153 }
154
155 bool Empty() const;
156
157 bool model_name_different() const { return model_name_different_; }
158 inline void set_model_name_different(bool value) {
159 model_name_different_ = value;
160 }
161
163 return primary_objective_name_different_;
164 }
165 inline void set_primary_objective_name_different(bool value) {
166 primary_objective_name_different_ = value;
167 }
168
169 private:
170 bool model_name_different_ = false;
171 bool primary_objective_name_different_ = false;
172 std::array<ElementDifference, kNumElements> elements_;
173 template <int i>
174 using StorageForAttr = AttributeDifference<AllAttrs::Type<i>>;
176};
177
179// Template function implementations
181
182template <typename T>
183absl::flat_hash_set<T> IntersectSets(const absl::flat_hash_set<T>& first,
184 const absl::flat_hash_set<T>& second) {
185 absl::flat_hash_set<T> result;
186 for (const T& f : first) {
187 if (second.contains(f)) {
188 result.insert(f);
189 }
190 }
191 return result;
192}
193
194template <typename T>
196 const absl::flat_hash_set<T>& first, const absl::flat_hash_set<T>& second) {
197 for (const T& f : first) {
198 if (!second.contains(f)) {
199 only_in_first.insert(f);
200 }
201 }
202 for (const T& s : second) {
203 if (!first.contains(s)) {
204 only_in_second.insert(s);
205 }
206 }
207}
208
209template <typename AttrType>
210std::vector<typename ElementalDifference::AttributeDifference<AttrType>::Key>
212 std::vector<Key> result;
213 for (Key key : keys.only_in_first) {
214 result.push_back(key);
215 }
216 for (Key key : keys.only_in_second) {
217 result.push_back(key);
218 }
219 for (Key key : different_values) {
220 result.push_back(key);
221 }
222 absl::c_sort(result);
223 return result;
224}
225
226template <typename AttrType>
228 return keys.Empty() && different_values.empty();
230
231} // namespace operations_research::math_opt
232
233#endif // OR_TOOLS_MATH_OPT_ELEMENTAL_ELEMENTAL_DIFFERENCER_H_
const AttributeDifference< AttrType > & attr_difference(const AttrType a) const
AttributeDifference< AttrType > & mutable_attr_difference(const AttrType a)
static ElementalDifference Create(const Elemental &first, const Elemental &second, const ElementalDifferenceOptions &options={})
Returns the difference between two Elementals.
ElementDifference & mutable_element_difference(const ElementType e)
const ElementDifference & element_difference(const ElementType e) const
static std::string Describe(const Elemental &first, const Elemental &second, const ElementalDifference &difference)
static std::string DescribeDifference(const Elemental &first, const Elemental &second, const ElementalDifferenceOptions &options={})
Returns a string describing the difference between two models.
An object oriented wrapper for quadratic constraints in ModelStorage.
Definition gurobi_isv.cc:28
AttrKey< AttrTypeDescriptorT< AttrType >::kNumKeyElements, typename AttrTypeDescriptorT< AttrType >::Symmetry > AttrKeyFor
The type of the AttrKey for attribute type AttrType.
absl::flat_hash_set< T > IntersectSets(const absl::flat_hash_set< T > &first, const absl::flat_hash_set< T > &second)
Returns the elements in both first and second.
bool Empty() const
Indicates that there are no differences for this attribute.
bool next_id_different
The value of next_id for this ElementType differs.
bool Empty() const
Indicates there are no differences for this ElementType.
SymmetricDifference< int64_t > ids
Element ids in one elemental but not in the other.
absl::flat_hash_set< int64_t > different_names
Element ids in both elementals where the element names disagree.