diff --git a/src/constraint_solver/constraint_solveri.h b/src/constraint_solver/constraint_solveri.h index a6b14ce6ca..6852f11790 100644 --- a/src/constraint_solver/constraint_solveri.h +++ b/src/constraint_solver/constraint_solveri.h @@ -2464,6 +2464,11 @@ class UnsortedNullableRevBitset { // the active bitset was changed in the process. bool RevSubtract(Solver* const solver, const std::vector& mask); + // This method ands the mask with the active bitset. It returns true if + // the active bitset was changed in the process. + bool RevAnd(Solver* const solver, const std::vector& mask); + + // This method returns the number of non null 64 bit words in the bitset // representation. int ActiveWordSize() const { return active_words_.Size(); } diff --git a/src/constraint_solver/table.cc b/src/constraint_solver/table.cc index 2c4969a684..8e0bfac82c 100644 --- a/src/constraint_solver/table.cc +++ b/src/constraint_solver/table.cc @@ -566,6 +566,7 @@ class CompactPositiveTableConstraint : public BasePositiveTableConstraint { case 1: { SetTempMask(var_index, var->Min() - omin); changed = AndTempMaskWithActive(); + // changed = AndMaskWithActive(var_index, var->Min() - omin); break; } case 2: { @@ -720,10 +721,17 @@ class CompactPositiveTableConstraint : public BasePositiveTableConstraint { // ----- Helpers during propagation ----- bool AndTempMaskWithActive() { - for (int i : active_tuples_.active_words()) { - temp_mask_[i] = ~temp_mask_[i]; + const bool result = active_tuples_.RevAnd(solver(), temp_mask_); + if (active_tuples_.Empty()) { + solver()->Fail(); } - const bool result = active_tuples_.RevSubtract(solver(), temp_mask_); + return result; + } + + bool AndMaskWithActive(int var_index, int64 value_index) { + CHECK_EQ(masks_[var_index][value_index].size(), word_length_); + const bool result = + active_tuples_.RevAnd(solver(), masks_[var_index][value_index]); if (active_tuples_.Empty()) { solver()->Fail(); } diff --git a/src/constraint_solver/utilities.cc b/src/constraint_solver/utilities.cc index 3d18c7c10c..75ab9a980f 100644 --- a/src/constraint_solver/utilities.cc +++ b/src/constraint_solver/utilities.cc @@ -239,18 +239,40 @@ void UnsortedNullableRevBitset::Init(Solver* const solver, bool UnsortedNullableRevBitset::RevSubtract(Solver* const solver, const std::vector& mask) { bool changed = false; - for (int i = 0; i < active_words_.Size(); ++i) { - const int index = active_words_.Element(i); + for (int index : active_words_) { if (bits_[index] & mask[index]) { changed = true; bits_.SetValue(solver, index, bits_[index] & ~mask[index]); } } // Update active_words_ in reverse order. - for (int i = active_words_.Size() - 1; i >= 0; --i) { - const int index = active_words_.Element(i); - if (!bits_[index]) { - active_words_.Remove(solver, index); + if (changed) { + for (int i = active_words_.Size() - 1; i >= 0; --i) { + const int index = active_words_.Element(i); + if (!bits_[index]) { + active_words_.Remove(solver, index); + } + } + } + return changed; +} + +bool UnsortedNullableRevBitset::RevAnd(Solver* const solver, + const std::vector& mask) { + bool changed = false; + for (int index : active_words_) { + if (bits_[index] & ~mask[index]) { + changed = true; + bits_.SetValue(solver, index, bits_[index] & mask[index]); + } + } + // Update active_words_ in reverse order. + if (changed) { + for (int i = active_words_.Size() - 1; i >= 0; --i) { + const int index = active_words_.Element(i); + if (!bits_[index]) { + active_words_.Remove(solver, index); + } } } return changed; @@ -263,8 +285,7 @@ bool UnsortedNullableRevBitset::Intersects(const std::vector& mask, if (mask[*support_index] & bits_[*support_index]) { return true; } - for (int i = 0; i < active_words_.Size(); ++i) { - const int index = active_words_.Element(i); + for (int index : active_words_) { if (bits_[index] & mask[index]) { *support_index = index; return true;