18 #include "absl/strings/str_format.h"
32 class Diffn :
public Constraint {
34 Diffn(Solver*
const solver,
const std::vector<IntVar*>& x_vars,
35 const std::vector<IntVar*>& y_vars,
const std::vector<IntVar*>& x_size,
36 const std::vector<IntVar*>& y_size,
bool strict)
45 CHECK_EQ(x_vars.size(), y_vars.size());
46 CHECK_EQ(x_vars.size(), x_size.size());
47 CHECK_EQ(x_vars.size(), y_size.size());
52 void Post()
override {
53 Solver*
const s = solver();
54 for (
int i = 0; i < size_; ++i) {
56 s,
this, &Diffn::OnBoxRangeChange,
"OnBoxRangeChange", i);
57 x_[i]->WhenRange(demon);
58 y_[i]->WhenRange(demon);
59 dx_[i]->WhenRange(demon);
60 dy_[i]->WhenRange(demon);
64 if (solver()->
parameters().diffn_use_cumulative() &&
65 IsArrayInRange<int64>(x_, 0,
kint64max) &&
66 IsArrayInRange<int64>(y_, 0,
kint64max)) {
67 Constraint* ct1 =
nullptr;
68 Constraint* ct2 =
nullptr;
82 std::vector<int64> size_x;
84 ct1 = MakeCumulativeConstraint(x_, size_x, dy_,
85 max_size_y + max_y - min_y);
88 std::vector<int64> size_y;
90 ct2 = MakeCumulativeConstraint(y_, size_y, dx_,
91 max_size_x + max_x - min_x);
95 s->AddConstraint(ct1);
98 s->AddConstraint(ct2);
103 void InitialPropagate()
override {
105 for (
int i = 0; i < size_; ++i) {
111 to_propagate_.clear();
112 for (
int i = 0; i < size_; i++) {
113 to_propagate_.insert(i);
118 std::string DebugString()
const override {
119 return absl::StrFormat(
120 "Diffn(x = [%s], y = [%s], dx = [%s], dy = [%s]))",
125 void Accept(ModelVisitor*
const visitor)
const override {
126 visitor->BeginVisitConstraint(ModelVisitor::kDisjunctive,
this);
127 visitor->VisitIntegerVariableArrayArgument(ModelVisitor::kPositionXArgument,
129 visitor->VisitIntegerVariableArrayArgument(ModelVisitor::kPositionYArgument,
131 visitor->VisitIntegerVariableArrayArgument(ModelVisitor::kSizeXArgument,
133 visitor->VisitIntegerVariableArrayArgument(ModelVisitor::kSizeYArgument,
135 visitor->EndVisitConstraint(ModelVisitor::kDisjunctive,
this);
139 void PropagateAll() {
140 for (
const int box : to_propagate_) {
142 FailWhenEnergyIsTooLarge(box);
143 PushOverlappingBoxes(box);
145 to_propagate_.clear();
146 fail_stamp_ = solver()->fail_stamp();
149 void OnBoxRangeChange(
int box) {
150 if (solver()->fail_stamp() > fail_stamp_ && !to_propagate_.empty()) {
153 fail_stamp_ = solver()->fail_stamp();
154 to_propagate_.clear();
156 to_propagate_.insert(box);
157 EnqueueDelayedDemon(delayed_demon_);
160 bool CanBoxedOverlap(
int i,
int j)
const {
161 if (AreBoxedDisjoingHorizontallyForSure(i, j) ||
162 AreBoxedDisjoingVerticallyForSure(i, j)) {
168 bool AreBoxedDisjoingHorizontallyForSure(
int i,
int j)
const {
169 return (x_[i]->Min() >= x_[j]->Max() + dx_[j]->Max()) ||
170 (x_[j]->Min() >= x_[i]->Max() + dx_[i]->Max()) ||
171 (!strict_ && (dx_[i]->Min() == 0 || dx_[j]->Min() == 0));
174 bool AreBoxedDisjoingVerticallyForSure(
int i,
int j)
const {
175 return (y_[i]->Min() >= y_[j]->Max() + dy_[j]->Max()) ||
176 (y_[j]->Min() >= y_[i]->Max() + dy_[i]->Max()) ||
177 (!strict_ && (dy_[i]->Min() == 0 || dy_[j]->Min() == 0));
181 void FillNeighbors(
int box) {
185 for (
int other = 0; other < size_; ++other) {
186 if (other != box && CanBoxedOverlap(other, box)) {
187 neighbors_.push_back(other);
195 void FailWhenEnergyIsTooLarge(
int box) {
196 int64 area_min_x = x_[box]->Min();
197 int64 area_max_x = x_[box]->Max() + dx_[box]->Max();
198 int64 area_min_y = y_[box]->Min();
199 int64 area_max_y = y_[box]->Max() + dy_[box]->Max();
200 int64 sum_of_areas = dx_[box]->Min() * dy_[box]->Min();
203 for (
int i = 0; i < neighbors_.size(); ++i) {
204 const int other = neighbors_[i];
206 area_min_x =
std::min(area_min_x, x_[other]->Min());
207 area_max_x =
std::max(area_max_x, x_[other]->Max() + dx_[other]->Max());
208 area_min_y =
std::min(area_min_y, y_[other]->Min());
209 area_max_y =
std::max(area_max_y, y_[other]->Max() + dy_[other]->Max());
211 sum_of_areas += dx_[other]->Min() * dy_[other]->Min();
212 const int64 bounding_area =
213 (area_max_x - area_min_x) * (area_max_y - area_min_y);
214 if (sum_of_areas > bounding_area) {
223 void PushOverlappingBoxes(
int box) {
224 for (
int i = 0; i < neighbors_.size(); ++i) {
225 PushOneBox(box, neighbors_[i]);
232 void PushOneBox(
int box,
int other) {
234 (x_[box]->Min() + dx_[box]->Min() <= x_[other]->Max()) +
235 2 * (x_[other]->Min() + dx_[other]->Min() <= x_[box]->Max()) +
236 4 * (y_[box]->Min() + dy_[box]->Min() <= y_[other]->Max()) +
237 8 * (y_[other]->Min() + dy_[other]->Min() <= y_[box]->Max());
246 x_[other]->SetMin(x_[box]->Min() + dx_[box]->Min());
247 x_[box]->SetMax(x_[other]->Max() - dx_[box]->Min());
248 dx_[box]->SetMax(x_[other]->Max() - x_[box]->Min());
252 x_[box]->SetMin(x_[other]->Min() + dx_[other]->Min());
253 x_[other]->SetMax(x_[box]->Max() - dx_[other]->Min());
254 dx_[other]->SetMax(x_[box]->Max() - x_[other]->Min());
258 y_[other]->SetMin(y_[box]->Min() + dy_[box]->Min());
259 y_[box]->SetMax(y_[other]->Max() - dy_[box]->Min());
260 dy_[box]->SetMax(y_[other]->Max() - y_[box]->Min());
264 y_[box]->SetMin(y_[other]->Min() + dy_[other]->Min());
265 y_[other]->SetMax(y_[box]->Max() - dy_[other]->Min());
266 dy_[other]->SetMax(y_[box]->Max() - y_[other]->Min());
275 Constraint* MakeCumulativeConstraint(
const std::vector<IntVar*>& positions,
276 const std::vector<int64>& sizes,
277 const std::vector<IntVar*>& demands,
279 std::vector<IntervalVar*> intervals;
280 solver()->MakeFixedDurationIntervalVarArray(positions, sizes,
"interval",
282 return solver()->MakeCumulative(intervals, demands,
capacity,
"cumul");
285 std::vector<IntVar*> x_;
286 std::vector<IntVar*> y_;
287 std::vector<IntVar*> dx_;
288 std::vector<IntVar*> dy_;
291 Demon* delayed_demon_;
292 absl::flat_hash_set<int> to_propagate_;
293 std::vector<int> neighbors_;
298 Constraint* Solver::MakeNonOverlappingBoxesConstraint(
299 const std::vector<IntVar*>& x_vars,
const std::vector<IntVar*>& y_vars,
300 const std::vector<IntVar*>& x_size,
const std::vector<IntVar*>& y_size) {
301 return RevAlloc(
new Diffn(
this, x_vars, y_vars, x_size, y_size,
true));
304 Constraint* Solver::MakeNonOverlappingBoxesConstraint(
305 const std::vector<IntVar*>& x_vars,
const std::vector<IntVar*>& y_vars,
306 const std::vector<int64>& x_size,
const std::vector<int64>& y_size) {
307 std::vector<IntVar*> dx(x_size.size());
308 std::vector<IntVar*> dy(y_size.size());
309 for (
int i = 0; i < x_size.size(); ++i) {
310 dx[i] = MakeIntConst(x_size[i]);
311 dy[i] = MakeIntConst(y_size[i]);
313 return RevAlloc(
new Diffn(
this, x_vars, y_vars, dx, dy,
true));
316 Constraint* Solver::MakeNonOverlappingBoxesConstraint(
317 const std::vector<IntVar*>& x_vars,
const std::vector<IntVar*>& y_vars,
318 const std::vector<int>& x_size,
const std::vector<int>& y_size) {
319 std::vector<IntVar*> dx(x_size.size());
320 std::vector<IntVar*> dy(y_size.size());
321 for (
int i = 0; i < x_size.size(); ++i) {
322 dx[i] = MakeIntConst(x_size[i]);
323 dy[i] = MakeIntConst(y_size[i]);
325 return RevAlloc(
new Diffn(
this, x_vars, y_vars, dx, dy,
true));
328 Constraint* Solver::MakeNonOverlappingNonStrictBoxesConstraint(
329 const std::vector<IntVar*>& x_vars,
const std::vector<IntVar*>& y_vars,
330 const std::vector<IntVar*>& x_size,
const std::vector<IntVar*>& y_size) {
331 return RevAlloc(
new Diffn(
this, x_vars, y_vars, x_size, y_size,
false));
334 Constraint* Solver::MakeNonOverlappingNonStrictBoxesConstraint(
335 const std::vector<IntVar*>& x_vars,
const std::vector<IntVar*>& y_vars,
336 const std::vector<int64>& x_size,
const std::vector<int64>& y_size) {
337 std::vector<IntVar*> dx(x_size.size());
338 std::vector<IntVar*> dy(y_size.size());
339 for (
int i = 0; i < x_size.size(); ++i) {
340 dx[i] = MakeIntConst(x_size[i]);
341 dy[i] = MakeIntConst(y_size[i]);
343 return RevAlloc(
new Diffn(
this, x_vars, y_vars, dx, dy,
false));
346 Constraint* Solver::MakeNonOverlappingNonStrictBoxesConstraint(
347 const std::vector<IntVar*>& x_vars,
const std::vector<IntVar*>& y_vars,
348 const std::vector<int>& x_size,
const std::vector<int>& y_size) {
349 std::vector<IntVar*> dx(x_size.size());
350 std::vector<IntVar*> dy(y_size.size());
351 for (
int i = 0; i < x_size.size(); ++i) {
352 dx[i] = MakeIntConst(x_size[i]);
353 dy[i] = MakeIntConst(y_size[i]);
355 return RevAlloc(
new Diffn(
this, x_vars, y_vars, dx, dy,
false));