20#include "absl/log/check.h"
21#include "absl/types/span.h"
33 absl::Span<const Literal> enforcement_literals,
34 const std::vector<Literal>& literals,
bool value,
Model* model)
35 : literals_(literals),
37 trail_(*model->GetOrCreate<
Trail>()),
41 enforcement_id_ = enforcement_helper_.
Register(enforcement_literals, watcher,
42 RegisterWith(watcher));
53 int unassigned_index = -1;
54 for (
int i = 0;
i < literals_.size(); ++
i) {
56 if (trail_.Assignment().LiteralIsFalse(l)) {
58 }
else if (trail_.Assignment().LiteralIsTrue(l)) {
62 if (unassigned_index != -1)
return true;
67 auto fill_literal_reason = [&]() {
68 literal_reason_.clear();
69 for (
int i = 0;
i < literals_.size(); ++
i) {
70 if (
i == unassigned_index)
continue;
72 literal_reason_.push_back(
73 trail_.Assignment().LiteralIsFalse(l) ? l : l.
Negated());
79 fill_literal_reason();
80 const Literal u = literals_[unassigned_index];
81 return enforcement_helper_.EnqueueLiteral(
82 enforcement_id_, sum == value_ ? u.
Negated() : u, literal_reason_,
87 if (sum == value_)
return true;
91 fill_literal_reason();
92 return enforcement_helper_.ReportConflict(enforcement_id_, literal_reason_,
94 }
else if (unassigned_index == -1) {
95 fill_literal_reason();
96 return enforcement_helper_.PropagateWhenFalse(
97 enforcement_id_, literal_reason_, {});
104 const int id = watcher->
Register(
this);
105 for (
const Literal& l : literals_) {
113 IntegerVariable target_var,
const absl::Span<const AffineExpression> exprs,
114 const absl::Span<const Literal> selectors,
115 const absl::Span<const Literal> enforcements,
Model* model)
116 : target_var_(target_var),
117 enforcements_(enforcements.
begin(), enforcements.
end()),
118 selectors_(selectors.
begin(), selectors.
end()),
120 trail_(model->GetOrCreate<
Trail>()),
126 const int first_non_false = id;
130 CHECK_EQ(to_explain.
var, target_var_);
131 const IntegerValue target_min = to_explain.
bound;
135 auto& literals_at_false = integer_trail_->ClearedMutableTmpLiterals();
136 for (
int i = 0;
i < first_non_false; ++
i) {
141 if (integer_trail_->LevelZeroLowerBound(exprs_[
i]) >= target_min) {
145 literals_at_false.push_back(selectors_[
i]);
150 auto& integer_literals = integer_trail_->ClearedMutableTmpIntegerLiterals();
152 absl::MakeSpan(exprs_).subspan(first_non_false)) {
153 if (expr.IsConstant()) {
154 DCHECK_GE(expr.constant, target_min);
159 if (integer_trail_->IsTrueAtLevelZero(to_explain))
continue;
160 integer_literals.push_back(to_explain);
168 for (
const Literal l : enforcements_) {
169 if (!trail_->Assignment().LiteralIsTrue(l))
return true;
176 const IntegerValue current_min = integer_trail_->LowerBound(target_var_);
179 int first_non_false = 0;
180 const int size = exprs_.size();
181 Literal*
const selectors = selectors_.data();
183 for (
int i = 0;
i < size; ++
i) {
188 if (
i != first_non_false) {
189 std::swap(selectors[
i], selectors[first_non_false]);
190 std::swap(exprs[
i], exprs[first_non_false]);
196 const IntegerValue min = integer_trail_->LowerBound(exprs[
i]);
197 if (min < target_min) {
201 if (target_min <= current_min)
return true;
207 *(trail_->MutableConflict()) = selectors_;
212 return integer_trail_->EnqueueWithLazyReason(
214 first_non_false, target_min,
this);
219 const int id = watcher->
Register(
this);
223 if (!e.IsConstant()) {
bool LiteralIsFalse(Literal literal) const
bool LiteralIsTrue(Literal literal) const
BooleanXorPropagator(absl::Span< const Literal > enforcement_literals, const std::vector< Literal > &literals, bool value, Model *model)
void WatchLiteral(Literal l, int id, int watch_index=-1)
void WatchLowerBound(IntegerVariable var, int id, int watch_index=-1)
int Register(PropagatorInterface *propagator)
void RegisterWith(GenericLiteralWatcher *watcher)
GreaterThanAtLeastOneOfPropagator(IntegerVariable target_var, absl::Span< const AffineExpression > exprs, absl::Span< const Literal > selectors, absl::Span< const Literal > enforcements, Model *model)
void Explain(int id, IntegerLiteral to_explain, IntegerReason *reason) final
constexpr IntegerValue kMaxIntegerValue(std::numeric_limits< IntegerValue::ValueType >::max() - 1)
const IntegerVariable kNoIntegerVariable(-1)
ClosedInterval::Iterator end(ClosedInterval interval)
ClosedInterval::Iterator begin(ClosedInterval interval)
static IntegerLiteral GreaterOrEqual(IntegerVariable i, IntegerValue bound)
absl::Span< const Literal > boolean_literals_at_false
absl::Span< const Literal > boolean_literals_at_true
absl::Span< const IntegerLiteral > integer_literals