23#include "absl/algorithm/container.h"
24#include "absl/container/flat_hash_map.h"
25#include "absl/container/inlined_vector.h"
26#include "absl/log/check.h"
27#include "absl/log/log.h"
28#include "absl/types/span.h"
51 trail_(model->GetOrCreate<
Trail>()),
56void Precedences2DPropagator::UpdateVarLookups() {
57 var_to_box_and_coeffs_.clear();
58 for (
int dim = 0; dim < 2; ++dim) {
61 for (
int j = 0; j < 2; ++j) {
62 const absl::Span<const AffineExpression> interval_points =
63 j == 0 ? dim_helper.
Starts() : dim_helper.
Ends();
65 const IntegerVariable var = interval_points[
i].var;
75void Precedences2DPropagator::AddOrUpdateDataForPairOfBoxes(
int box1,
77 if (box1 > box2) std::swap(box1, box2);
78 const auto [it, inserted] = non_trivial_pairs_index_.insert(
79 {std::make_pair(box1, box2),
static_cast<int>(pair_data_.size())});
80 absl::InlinedVector<Literal, 4> presence_literals;
81 for (
int dim = 0; dim < 2; ++dim) {
82 const SchedulingConstraintHelper& dim_helper =
83 dim == 0 ? helper_.x_helper() : helper_.y_helper();
84 for (
const int box : {box1, box2}) {
85 if (dim_helper.IsOptional(box)) {
86 presence_literals.push_back(dim_helper.PresenceLiteral(box));
92 pair_data_.emplace_back(
93 PairData{.pair_presence_literals = {presence_literals.begin(),
94 presence_literals.end()},
98 PairData& pair_data = pair_data_[it->second];
99 for (
int dim = 0; dim < 2; ++dim) {
100 const SchedulingConstraintHelper& dim_helper =
101 dim == 0 ? helper_.x_helper() : helper_.y_helper();
102 for (
int j = 0; j < 2; ++j) {
103 int b1 = j == 0 ? box1 : box2;
104 int b2 = j == 0 ? box2 : box1;
105 auto [start_minus_end_expr, start_minus_end_ub] =
107 dim_helper.Ends()[b2], 0);
108 const LinearExpression2Index start_minus_end_index =
109 lin2_indices_->GetIndex(start_minus_end_expr);
110 pair_data.start_before_end[dim][j].ub = start_minus_end_ub;
112 pair_data.start_before_end[dim][j].linear2 = start_minus_end_index;
114 pair_data.start_before_end[dim][j].linear2 = start_minus_end_expr;
120void Precedences2DPropagator::CollectNewPairsOfBoxesWithNonTrivialDistance() {
121 const absl::Span<const LinearExpression2> exprs =
122 lin2_indices_->GetStoredLinear2Indices();
123 if (exprs.size() == num_known_linear2_) {
126 VLOG(2) <<
"CollectPairsOfBoxesWithNonTrivialDistance called, num_exprs: "
128 for (; num_known_linear2_ < exprs.size(); ++num_known_linear2_) {
129 const LinearExpression2& positive_expr = exprs[num_known_linear2_];
130 LinearExpression2 negated_expr = positive_expr;
131 negated_expr.Negate();
132 for (
const LinearExpression2& expr : {positive_expr, negated_expr}) {
135 if (it1 == var_to_box_and_coeffs_.end()) {
138 if (it2 == var_to_box_and_coeffs_.end()) {
142 const VarUsage& usage1 = it1->second;
143 const VarUsage& usage2 = it2->second;
144 for (
int dim = 0; dim < 2; ++dim) {
145 for (
const int box1 : usage1.boxes[dim][0 ]) {
146 for (
const int box2 : usage2.boxes[dim][1 ]) {
147 if (box1 == box2)
continue;
148 AddOrUpdateDataForPairOfBoxes(box1, box2);
156IntegerValue Precedences2DPropagator::UpperBound(
157 std::variant<LinearExpression2, LinearExpression2Index> linear2)
const {
158 if (std::holds_alternative<LinearExpression2Index>(linear2)) {
159 return linear2_bounds_->UpperBound(
160 std::get<LinearExpression2Index>(linear2));
162 return integer_trail_->UpperBound(std::get<LinearExpression2>(linear2));
167 if (!helper_.IsEnforced())
return true;
168 if (last_helper_inprocessing_count_ != helper_.InProcessingCount()) {
169 if (!helper_.SynchronizeAndSetDirection())
return false;
170 last_helper_inprocessing_count_ = helper_.InProcessingCount();
172 num_known_linear2_ = 0;
173 non_trivial_pairs_index_.clear();
176 CollectNewPairsOfBoxesWithNonTrivialDistance();
180 for (
const PairData& pair_data : pair_data_) {
181 if (!absl::c_all_of(pair_data.pair_presence_literals,
182 [
this](
const Literal& literal) {
183 return trail_->Assignment().LiteralIsTrue(literal);
188 bool is_unfeasible =
true;
189 for (
int dim = 0; dim < 2; dim++) {
190 for (
int j = 0; j < 2; j++) {
192 pair_data.start_before_end[dim][j];
193 if (UpperBound(start_before_end.
linear2) >= start_before_end.
ub) {
194 is_unfeasible =
false;
198 if (!is_unfeasible)
break;
200 if (!is_unfeasible)
continue;
203 if (!helper_.SynchronizeAndSetDirection())
return false;
205 const int box1 = pair_data.box1;
206 const int box2 = pair_data.box2;
207 helper_.ResetReason();
210 helper_.x_helper().AddReasonForBeingBeforeAssumingNoOverlap(box1, box2);
211 helper_.x_helper().AddReasonForBeingBeforeAssumingNoOverlap(box2, box1);
212 helper_.y_helper().AddReasonForBeingBeforeAssumingNoOverlap(box1, box2);
213 helper_.y_helper().AddReasonForBeingBeforeAssumingNoOverlap(box2, box1);
215 helper_.AddPresenceReason(box1);
216 helper_.AddPresenceReason(box2);
217 return helper_.ReportConflict();
223 const int id = watcher->
Register(
this);
224 helper_.WatchAllBoxes(
id);
225 linear2_watcher_->WatchAllLinearExpressions2(
id);
230 if (!VLOG_IS_ON(1))
return;
231 std::vector<std::pair<std::string, int64_t>> stats;
232 stats.push_back({
"Precedences2DPropagator/called", num_calls_});
233 stats.push_back({
"Precedences2DPropagator/conflicts", num_conflicts_});
234 stats.push_back({
"Precedences2DPropagator/pairs", pair_data_.size()});
236 shared_stats_->AddStats(stats);
int Register(PropagatorInterface *propagator)
void SetPushAffineUbForBinaryRelation()
SchedulingConstraintHelper & y_helper() const
SchedulingConstraintHelper & x_helper() const
int RegisterWith(GenericLiteralWatcher *watcher)
Precedences2DPropagator(NoOverlap2DConstraintHelper *helper, Model *model)
~Precedences2DPropagator() override
absl::Span< const AffineExpression > Starts() const
absl::Span< const AffineExpression > Ends() const
void STLSortAndRemoveDuplicates(T *v, const LessFunc &less_func)
const LinearExpression2Index kNoLinearExpression2Index(-1)
const IntegerVariable kNoIntegerVariable(-1)
IntegerVariable PositiveVariable(IntegerVariable i)
std::pair< LinearExpression2, IntegerValue > EncodeDifferenceLowerThan(AffineExpression a, AffineExpression b, IntegerValue ub)
std::variant< LinearExpression2, LinearExpression2Index > linear2