20 #include "absl/strings/str_format.h" 33 class Diffn :
public Constraint {
35 Diffn(Solver*
const solver,
const std::vector<IntVar*>& x_vars,
36 const std::vector<IntVar*>& y_vars,
const std::vector<IntVar*>& x_size,
37 const std::vector<IntVar*>& y_size,
bool strict)
46 CHECK_EQ(x_vars.size(), y_vars.size());
47 CHECK_EQ(x_vars.size(), x_size.size());
48 CHECK_EQ(x_vars.size(), y_size.size());
53 void Post()
override {
54 Solver*
const s = solver();
55 for (
int i = 0; i < size_; ++i) {
57 s,
this, &Diffn::OnBoxRangeChange,
"OnBoxRangeChange", i);
58 x_[i]->WhenRange(demon);
59 y_[i]->WhenRange(demon);
60 dx_[i]->WhenRange(demon);
61 dy_[i]->WhenRange(demon);
65 if (solver()->
parameters().diffn_use_cumulative() &&
68 Constraint* ct1 =
nullptr;
69 Constraint* ct2 =
nullptr;
83 std::vector<int64_t> size_x;
85 ct1 = MakeCumulativeConstraint(x_, size_x, dy_,
86 max_size_y + max_y - min_y);
89 std::vector<int64_t> size_y;
91 ct2 = MakeCumulativeConstraint(y_, size_y, dx_,
92 max_size_x + max_x - min_x);
96 s->AddConstraint(ct1);
99 s->AddConstraint(ct2);
104 void InitialPropagate()
override {
106 for (
int i = 0; i < size_; ++i) {
112 to_propagate_.clear();
113 for (
int i = 0; i < size_; i++) {
114 to_propagate_.insert(i);
119 std::string DebugString()
const override {
120 return absl::StrFormat(
121 "Diffn(x = [%s], y = [%s], dx = [%s], dy = [%s]))",
126 void Accept(ModelVisitor*
const visitor)
const override {
140 void PropagateAll() {
141 for (
const int box : to_propagate_) {
143 FailWhenEnergyIsTooLarge(box);
144 PushOverlappingBoxes(box);
146 to_propagate_.clear();
147 fail_stamp_ = solver()->fail_stamp();
150 void OnBoxRangeChange(
int box) {
151 if (solver()->fail_stamp() > fail_stamp_ && !to_propagate_.empty()) {
154 fail_stamp_ = solver()->fail_stamp();
155 to_propagate_.clear();
157 to_propagate_.insert(box);
158 EnqueueDelayedDemon(delayed_demon_);
161 bool CanBoxedOverlap(
int i,
int j)
const {
162 if (AreBoxedDisjoingHorizontallyForSure(i, j) ||
163 AreBoxedDisjoingVerticallyForSure(i, j)) {
169 bool AreBoxedDisjoingHorizontallyForSure(
int i,
int j)
const {
170 return (x_[i]->Min() >= x_[j]->Max() + dx_[j]->Max()) ||
171 (x_[j]->Min() >= x_[i]->Max() + dx_[i]->Max()) ||
172 (!strict_ && (dx_[i]->Min() == 0 || dx_[j]->Min() == 0));
175 bool AreBoxedDisjoingVerticallyForSure(
int i,
int j)
const {
176 return (y_[i]->Min() >= y_[j]->Max() + dy_[j]->Max()) ||
177 (y_[j]->Min() >= y_[i]->Max() + dy_[i]->Max()) ||
178 (!strict_ && (dy_[i]->Min() == 0 || dy_[j]->Min() == 0));
182 void FillNeighbors(
int box) {
186 for (
int other = 0; other < size_; ++other) {
187 if (other != box && CanBoxedOverlap(other, box)) {
188 neighbors_.push_back(other);
196 void FailWhenEnergyIsTooLarge(
int box) {
197 int64_t area_min_x = x_[box]->Min();
198 int64_t area_max_x = x_[box]->Max() + dx_[box]->Max();
199 int64_t area_min_y = y_[box]->Min();
200 int64_t area_max_y = y_[box]->Max() + dy_[box]->Max();
201 int64_t sum_of_areas = dx_[box]->Min() * dy_[box]->Min();
204 for (
int i = 0; i < neighbors_.size(); ++i) {
205 const int other = neighbors_[i];
207 area_min_x =
std::min(area_min_x, x_[other]->Min());
208 area_max_x =
std::max(area_max_x, x_[other]->Max() + dx_[other]->Max());
209 area_min_y =
std::min(area_min_y, y_[other]->Min());
210 area_max_y =
std::max(area_max_y, y_[other]->Max() + dy_[other]->Max());
212 sum_of_areas += dx_[other]->Min() * dy_[other]->Min();
213 const int64_t bounding_area =
214 (area_max_x - area_min_x) * (area_max_y - area_min_y);
215 if (sum_of_areas > bounding_area) {
224 void PushOverlappingBoxes(
int box) {
225 for (
int i = 0; i < neighbors_.size(); ++i) {
226 PushOneBox(box, neighbors_[i]);
233 void PushOneBox(
int box,
int other) {
235 (x_[box]->Min() + dx_[box]->Min() <= x_[other]->Max()) +
236 2 * (x_[other]->Min() + dx_[other]->Min() <= x_[box]->Max()) +
237 4 * (y_[box]->Min() + dy_[box]->Min() <= y_[other]->Max()) +
238 8 * (y_[other]->Min() + dy_[other]->Min() <= y_[box]->Max());
247 x_[other]->SetMin(x_[box]->Min() + dx_[box]->Min());
248 x_[box]->SetMax(x_[other]->Max() - dx_[box]->Min());
249 dx_[box]->SetMax(x_[other]->Max() - x_[box]->Min());
253 x_[box]->SetMin(x_[other]->Min() + dx_[other]->Min());
254 x_[other]->SetMax(x_[box]->Max() - dx_[other]->Min());
255 dx_[other]->SetMax(x_[box]->Max() - x_[other]->Min());
259 y_[other]->SetMin(y_[box]->Min() + dy_[box]->Min());
260 y_[box]->SetMax(y_[other]->Max() - dy_[box]->Min());
261 dy_[box]->SetMax(y_[other]->Max() - y_[box]->Min());
265 y_[box]->SetMin(y_[other]->Min() + dy_[other]->Min());
266 y_[other]->SetMax(y_[box]->Max() - dy_[other]->Min());
267 dy_[other]->SetMax(y_[box]->Max() - y_[other]->Min());
276 Constraint* MakeCumulativeConstraint(
const std::vector<IntVar*>& positions,
277 const std::vector<int64_t>& sizes,
278 const std::vector<IntVar*>& demands,
280 std::vector<IntervalVar*> intervals;
281 solver()->MakeFixedDurationIntervalVarArray(positions, sizes,
"interval",
283 return solver()->MakeCumulative(intervals, demands,
capacity,
"cumul");
286 std::vector<IntVar*> x_;
287 std::vector<IntVar*> y_;
288 std::vector<IntVar*> dx_;
289 std::vector<IntVar*> dy_;
292 Demon* delayed_demon_;
293 absl::flat_hash_set<int> to_propagate_;
294 std::vector<int> neighbors_;
295 uint64_t fail_stamp_;
300 const std::vector<IntVar*>& x_vars,
const std::vector<IntVar*>& y_vars,
301 const std::vector<IntVar*>& x_size,
const std::vector<IntVar*>& y_size) {
302 return RevAlloc(
new Diffn(
this, x_vars, y_vars, x_size, y_size,
true));
306 const std::vector<IntVar*>& x_vars,
const std::vector<IntVar*>& y_vars,
307 const std::vector<int64_t>& x_size,
const std::vector<int64_t>& y_size) {
308 std::vector<IntVar*> dx(x_size.size());
309 std::vector<IntVar*> dy(y_size.size());
310 for (
int i = 0; i < x_size.size(); ++i) {
314 return RevAlloc(
new Diffn(
this, x_vars, y_vars, dx, dy,
true));
318 const std::vector<IntVar*>& x_vars,
const std::vector<IntVar*>& y_vars,
319 const std::vector<int>& x_size,
const std::vector<int>& y_size) {
320 std::vector<IntVar*> dx(x_size.size());
321 std::vector<IntVar*> dy(y_size.size());
322 for (
int i = 0; i < x_size.size(); ++i) {
326 return RevAlloc(
new Diffn(
this, x_vars, y_vars, dx, dy,
true));
330 const std::vector<IntVar*>& x_vars,
const std::vector<IntVar*>& y_vars,
331 const std::vector<IntVar*>& x_size,
const std::vector<IntVar*>& y_size) {
332 return RevAlloc(
new Diffn(
this, x_vars, y_vars, x_size, y_size,
false));
336 const std::vector<IntVar*>& x_vars,
const std::vector<IntVar*>& y_vars,
337 const std::vector<int64_t>& x_size,
const std::vector<int64_t>& y_size) {
338 std::vector<IntVar*> dx(x_size.size());
339 std::vector<IntVar*> dy(y_size.size());
340 for (
int i = 0; i < x_size.size(); ++i) {
344 return RevAlloc(
new Diffn(
this, x_vars, y_vars, dx, dy,
false));
348 const std::vector<IntVar*>& x_vars,
const std::vector<IntVar*>& y_vars,
349 const std::vector<int>& x_size,
const std::vector<int>& y_size) {
350 std::vector<IntVar*> dx(x_size.size());
351 std::vector<IntVar*> dy(y_size.size());
352 for (
int i = 0; i < x_size.size(); ++i) {
356 return RevAlloc(
new Diffn(
this, x_vars, y_vars, dx, dy,
false));
Constraint * MakeNonOverlappingNonStrictBoxesConstraint(const std::vector< IntVar * > &x_vars, const std::vector< IntVar * > &y_vars, const std::vector< IntVar * > &x_size, const std::vector< IntVar * > &y_size)
This constraint states that all the boxes must not overlap.
static const char kSizeXArgument[]
static const char kDisjunctive[]
A constraint is the main modeling object.
void FillValues(const std::vector< IntVar * > &vars, std::vector< int64_t > *const values)
static const char kSizeYArgument[]
DEFINE_INT_TYPE(RoutingNodeIndex, int)
Defining common types used in the routing library outside the main RoutingModel class has several pur...
#define CHECK_EQ(val1, val2)
int64_t MaxVarArray(const std::vector< IntVar * > &vars)
T * RevAlloc(T *object)
Registers the given object as being reversible.
bool AreAllBound(const std::vector< IntVar * > &vars)
IntVar * MakeIntConst(int64_t val, const std::string &name)
IntConst will create a constant expression.
int64_t MinVarArray(const std::vector< IntVar * > &vars)
Collection of objects used to extend the Constraint Solver library.
std::string JoinDebugStringPtr(const std::vector< T > &v, const std::string &separator)
Demon * MakeDelayedConstraintDemon0(Solver *const s, T *const ct, void(T::*method)(), const std::string &name)
Constraint * MakeNonOverlappingBoxesConstraint(const std::vector< IntVar * > &x_vars, const std::vector< IntVar * > &y_vars, const std::vector< IntVar * > &x_size, const std::vector< IntVar * > &y_size)
This constraint states that all the boxes must not overlap.
Demon * MakeConstraintDemon1(Solver *const s, T *const ct, void(T::*method)(P), const std::string &name, P param1)
static const char kPositionXArgument[]
static const char kPositionYArgument[]