14 #ifndef OR_TOOLS_UTIL_AFFINE_RELATION_H_
15 #define OR_TOOLS_UTIL_AFFINE_RELATION_H_
87 Relation
Get(
int x)
const;
94 if (x >= size_.size())
return;
95 CHECK_NE(size_[x], kSizeForRemovedEntry) << x;
103 size_[x] = kSizeForRemovedEntry;
108 if (x >= representative_.size())
return 1;
113 const int kSizeForRemovedEntry = 0;
115 void IncreaseSizeOfMemberVectors(
int new_size) {
116 if (new_size <= representative_.size())
return;
117 for (
int i = representative_.size(); i < new_size; ++i) {
118 representative_.push_back(i);
120 offset_.resize(new_size, 0);
121 coeff_.resize(new_size, 1);
122 size_.resize(new_size, 1);
125 void CompressPath(
int x)
const {
130 while (parent != representative_[parent]) {
131 tmp_path_.push_back(parent);
132 parent = representative_[parent];
135 const int old_parent = representative_[
var];
136 offset_[
var] += coeff_[
var] * offset_[old_parent];
137 coeff_[
var] *= coeff_[old_parent];
138 representative_[
var] = parent;
145 mutable std::vector<int> representative_;
149 mutable std::vector<int64> coeff_;
150 mutable std::vector<int64> offset_;
158 std::vector<int> size_;
161 mutable std::vector<int> tmp_path_;
165 return TryAdd(x, y, coeff, offset,
true,
true);
169 bool allow_rep_x,
bool allow_rep_y) {
174 IncreaseSizeOfMemberVectors(
std::max(x, y) + 1);
175 CHECK_NE(size_[x], kSizeForRemovedEntry) << x;
176 CHECK_NE(size_[y], kSizeForRemovedEntry) << y;
179 const int rep_x = representative_[x];
180 const int rep_y = representative_[y];
181 if (rep_x == rep_y)
return false;
186 const int64 coeff_x = coeff_[x];
187 const int64 new_coeff = coeff * coeff_[y];
188 const int64 new_offset = coeff * offset_[y] + offset - offset_[x];
189 const bool condition1 =
190 allow_rep_y && (new_coeff % coeff_x == 0) && (new_offset % coeff_x == 0);
191 const bool condition2 = allow_rep_x && (coeff_x % new_coeff == 0) &&
192 (new_offset % new_coeff == 0);
193 if (condition1 && (!condition2 || size_[x] <= size_[y])) {
194 representative_[rep_x] = rep_y;
195 size_[rep_y] += size_[rep_x];
196 coeff_[rep_x] = new_coeff / coeff_x;
197 offset_[rep_x] = new_offset / coeff_x;
198 }
else if (condition2) {
199 representative_[rep_y] = rep_x;
200 size_[rep_x] += size_[rep_y];
201 coeff_[rep_y] = coeff_x / new_coeff;
202 offset_[rep_y] = -new_offset / new_coeff;
211 if (x >= representative_.size() || representative_[x] == x)
return {x, 1, 0};
213 return {representative_[x], coeff_[x], offset_[x]};
218 #endif // OR_TOOLS_UTIL_AFFINE_RELATION_H_