21#include "absl/container/flat_hash_map.h"
22#include "absl/log/check.h"
23#include "absl/log/log.h"
24#include "absl/types/span.h"
47void Precedences2DPropagator::CollectPairsOfBoxesWithNonTrivialDistance() {
49 non_trivial_pairs_.clear();
53 std::vector<int> boxes[2][2];
55 absl::flat_hash_map<IntegerVariable, VarUsage> var_to_box_and_coeffs;
57 for (
int dim = 0; dim < 2; ++dim) {
58 const SchedulingConstraintHelper& dim_helper =
60 for (
int j = 0; j < 2; ++j) {
61 const absl::Span<const AffineExpression> interval_points =
62 j == 0 ? dim_helper.Starts() : dim_helper.Ends();
73 VLOG(2) <<
"CollectPairsOfBoxesWithNonTrivialDistance called, num_exprs: "
74 << binary_relations_maps_->GetAllExpressionsWithAffineBounds().size();
75 for (
const LinearExpression2& expr :
76 binary_relations_maps_->GetAllExpressionsWithAffineBounds()) {
79 if (it1 == var_to_box_and_coeffs.end() ||
80 it2 == var_to_box_and_coeffs.end()) {
84 const VarUsage& usage1 = it1->second;
85 const VarUsage& usage2 = it2->second;
86 for (
int dim = 0; dim < 2; ++dim) {
87 const SchedulingConstraintHelper& dim_helper =
88 dim == 0 ? helper_.x_helper() : helper_.y_helper();
89 for (
const int box1 : usage1.boxes[dim][0 ]) {
90 for (
const int box2 : usage2.boxes[dim][1 ]) {
91 if (box1 == box2)
continue;
92 const AffineExpression& start = dim_helper.Starts()[box1];
93 const AffineExpression&
end = dim_helper.Ends()[box2];
94 LinearExpression2 expr2;
95 expr2.vars[0] = start.var;
96 expr2.vars[1] =
end.var;
97 expr2.coeffs[0] = start.coeff;
98 expr2.coeffs[1] = -
end.coeff;
99 expr2.SimpleCanonicalization();
103 non_trivial_pairs_.push_back({box1, box2});
105 non_trivial_pairs_.push_back({box2, box1});
117 if (!helper_.SynchronizeAndSetDirection())
return false;
118 if (last_helper_inprocessing_count_ != helper_.InProcessingCount() ||
119 helper_.x_helper().CurrentDecisionLevel() == 0 ||
120 last_num_expressions_ !=
121 binary_relations_maps_->NumExpressionsWithAffineBounds()) {
122 last_helper_inprocessing_count_ = helper_.InProcessingCount();
123 last_num_expressions_ =
124 binary_relations_maps_->NumExpressionsWithAffineBounds();
125 CollectPairsOfBoxesWithNonTrivialDistance();
131 &helper_.y_helper()};
133 for (
const auto& [box1, box2] : non_trivial_pairs_) {
134 DCHECK(box1 < helper_.NumBoxes());
135 DCHECK(box2 < helper_.NumBoxes());
136 DCHECK_NE(box1, box2);
137 if (!helper_.IsPresent(box1) || !helper_.IsPresent(box2)) {
141 bool is_unfeasible =
true;
142 for (
int dim = 0; dim < 2; dim++) {
144 for (
int j = 0; j < 2; j++) {
152 expr.
vars[1] = helper->
Ends()[b2].var;
155 const IntegerValue ub_of_start_minus_end_value =
156 binary_relations_maps_->UpperBound(expr) +
157 helper->
Starts()[b1].constant - helper->
Ends()[b2].constant;
158 if (ub_of_start_minus_end_value >= 0) {
159 is_unfeasible =
false;
163 if (!is_unfeasible)
break;
165 if (!is_unfeasible)
continue;
169 helper_.ClearReason();
172 for (
int dim = 0; dim < 2; dim++) {
174 for (
int j = 0; j < 2; j++) {
182 expr.
vars[1] = helper->
Ends()[b2].var;
185 binary_relations_maps_->AddReasonForUpperBoundLowerThan(
187 -(helper->
Starts()[b1].constant - helper->
Ends()[b2].constant) - 1,
188 helper_.x_helper().MutableLiteralReason(),
189 helper_.x_helper().MutableIntegerReason());
192 helper_.AddPresenceReason(box1);
193 helper_.AddPresenceReason(box2);
194 return helper_.ReportConflict();
200 const int id = watcher->
Register(
this);
201 helper_.WatchAllBoxes(
id);
202 binary_relations_maps_->WatchAllLinearExpressions2(
id);
207 if (!VLOG_IS_ON(1))
return;
208 std::vector<std::pair<std::string, int64_t>> stats;
209 stats.push_back({
"Precedences2DPropagator/called", num_calls_});
210 stats.push_back({
"Precedences2DPropagator/conflicts", num_conflicts_});
211 stats.push_back({
"Precedences2DPropagator/pairs", non_trivial_pairs_.size()});
213 shared_stats_->AddStats(stats);
int Register(PropagatorInterface *propagator)
Registers a propagator and returns its unique ids.
void SetPushAffineUbForBinaryRelation()
SchedulingConstraintHelper & y_helper() const
bool SynchronizeAndSetDirection(bool x_is_forward_after_swap=true, bool y_is_forward_after_swap=true, bool swap_x_and_y=false)
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
Simple class to add statistics by name and print them at the end.
void STLSortAndRemoveDuplicates(T *v, const LessFunc &less_func)
const IntegerVariable kNoIntegerVariable(-1)
IntegerVariable PositiveVariable(IntegerVariable i)
In SWIG mode, we don't want anything besides these top-level includes.
ClosedInterval::Iterator end(ClosedInterval interval)