19#include "absl/types/span.h"
31 int unassigned_index = -1;
32 for (
int i = 0;
i < literals_.size(); ++
i) {
34 if (trail_->Assignment().LiteralIsFalse(l)) {
36 }
else if (trail_->Assignment().LiteralIsTrue(l)) {
40 if (unassigned_index != -1)
return true;
46 if (unassigned_index != -1) {
47 literal_reason_.clear();
48 for (
int i = 0;
i < literals_.size(); ++
i) {
49 if (
i == unassigned_index)
continue;
51 literal_reason_.push_back(
52 trail_->Assignment().LiteralIsFalse(l) ? l : l.
Negated());
54 const Literal u = literals_[unassigned_index];
55 integer_trail_->EnqueueLiteral(sum == value_ ? u.
Negated() : u,
61 if (sum == value_)
return true;
64 std::vector<Literal>* conflict = trail_->MutableConflict();
66 for (
int i = 0;
i < literals_.size(); ++
i) {
68 conflict->push_back(trail_->Assignment().LiteralIsFalse(l) ? l
75 const int id = watcher->
Register(
this);
76 for (
const Literal& l : literals_) {
83 IntegerVariable target_var,
const absl::Span<const AffineExpression> exprs,
84 const absl::Span<const Literal> selectors,
85 const absl::Span<const Literal> enforcements,
Model* model)
86 : target_var_(target_var),
87 enforcements_(enforcements.begin(), enforcements.end()),
88 selectors_(selectors.begin(), selectors.end()),
89 exprs_(exprs.begin(), exprs.end()),
90 trail_(model->GetOrCreate<
Trail>()),
94 int id, IntegerValue propagation_slack, IntegerVariable ,
95 int , std::vector<Literal>* literals_reason,
96 std::vector<int>* trail_indices_reason) {
97 literals_reason->clear();
98 trail_indices_reason->clear();
100 const int first_non_false = id;
101 const IntegerValue target_min = propagation_slack;
103 for (
const Literal l : enforcements_) {
104 literals_reason->push_back(l.Negated());
106 for (
int i = 0;
i < first_non_false; ++
i) {
111 if (integer_trail_->LevelZeroLowerBound(exprs_[
i]) >= target_min) {
115 literals_reason->push_back(selectors_[
i]);
117 integer_trail_->AddAllGreaterThanConstantReason(
118 absl::MakeSpan(exprs_).subspan(first_non_false), target_min,
119 trail_indices_reason);
125 for (
const Literal l : enforcements_) {
126 if (!trail_->Assignment().LiteralIsTrue(l))
return true;
133 const IntegerValue current_min = integer_trail_->LowerBound(target_var_);
136 int first_non_false = 0;
137 const int size = exprs_.size();
138 Literal*
const selectors = selectors_.data();
140 for (
int i = 0;
i < size; ++
i) {
145 if (
i != first_non_false) {
146 std::swap(selectors[
i], selectors[first_non_false]);
147 std::swap(exprs[
i], exprs[first_non_false]);
153 const IntegerValue min = integer_trail_->LowerBound(exprs[
i]);
154 if (min < target_min) {
158 if (target_min <= current_min)
return true;
164 *(trail_->MutableConflict()) = selectors_;
169 return integer_trail_->EnqueueWithLazyReason(
171 first_non_false, target_min,
this);
176 const int id = watcher->
Register(
this);
180 if (!e.IsConstant()) {
bool LiteralIsFalse(Literal literal) const
bool LiteralIsTrue(Literal literal) const
void RegisterWith(GenericLiteralWatcher *watcher)
void WatchLiteral(Literal l, int id, int watch_index=-1)
void WatchLowerBound(IntegerVariable var, int id, int watch_index=-1)
int Register(PropagatorInterface *propagator)
Registers a propagator and returns its unique ids.
void Explain(int id, IntegerValue propagation_slack, IntegerVariable var_to_explain, int trail_index, std::vector< Literal > *literals_reason, std::vector< int > *trail_indices_reason) final
For LazyReasonInterface.
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)
constexpr IntegerValue kMaxIntegerValue(std::numeric_limits< IntegerValue::ValueType >::max() - 1)
In SWIG mode, we don't want anything besides these top-level includes.
static IntegerLiteral GreaterOrEqual(IntegerVariable i, IntegerValue bound)