@@ -272,8 +272,6 @@ bool NonOverlappingRectanglesEnergyPropagator::Propagate() {
272
272
.x_max = std::numeric_limits<IntegerValue>::min (),
273
273
.y_min = std::numeric_limits<IntegerValue>::max (),
274
274
.y_max = std::numeric_limits<IntegerValue>::min ()};
275
- IntegerValue max_x_item_size = IntegerValue (0 );
276
- IntegerValue max_y_item_size = IntegerValue (0 );
277
275
std::vector<RectangleInRange> active_box_ranges;
278
276
active_box_ranges.reserve (num_boxes);
279
277
for (int box = 0 ; box < num_boxes; ++box) {
@@ -293,8 +291,6 @@ bool NonOverlappingRectanglesEnergyPropagator::Propagate() {
293
291
.y_max = y_.StartMax (box) + y_.SizeMin (box)},
294
292
.x_size = x_.SizeMin (box),
295
293
.y_size = y_.SizeMin (box)});
296
- max_x_item_size = std::max (max_x_item_size, x_.SizeMin (box));
297
- max_y_item_size = std::max (max_y_item_size, y_.SizeMin (box));
298
294
}
299
295
300
296
if (active_box_ranges.size () < 2 ) {
@@ -314,8 +310,8 @@ bool NonOverlappingRectanglesEnergyPropagator::Propagate() {
314
310
return true ;
315
311
}
316
312
317
- std::optional<Conflict> best_conflict = FindConflict (
318
- std::move (active_box_ranges), max_x_item_size, max_y_item_size );
313
+ std::optional<Conflict> best_conflict =
314
+ FindConflict ( std::move (active_box_ranges));
319
315
if (!best_conflict.has_value ()) {
320
316
return true ;
321
317
}
@@ -328,8 +324,7 @@ bool NonOverlappingRectanglesEnergyPropagator::Propagate() {
328
324
IntegerValue best_explanation_size = best_conflict->items .size ();
329
325
bool refined = false ;
330
326
while (true ) {
331
- const std::optional<Conflict> conflict =
332
- FindConflict (best_conflict->items , max_x_item_size, max_y_item_size);
327
+ const std::optional<Conflict> conflict = FindConflict (best_conflict->items );
333
328
if (!conflict.has_value ()) break ;
334
329
// We prefer an explanation with the least number of boxes.
335
330
if (conflict->items .size () >= best_explanation_size) {
@@ -356,8 +351,7 @@ bool NonOverlappingRectanglesEnergyPropagator::Propagate() {
356
351
357
352
std::optional<NonOverlappingRectanglesEnergyPropagator::Conflict>
358
353
NonOverlappingRectanglesEnergyPropagator::FindConflict (
359
- std::vector<RectangleInRange> active_box_ranges,
360
- const IntegerValue& max_x_item_size, const IntegerValue& max_y_item_size) {
354
+ std::vector<RectangleInRange> active_box_ranges) {
361
355
const auto rectangles_with_too_much_energy =
362
356
FindRectanglesWithEnergyConflictMC (active_box_ranges, *random_, 1.0 , 0.8 );
363
357
@@ -385,25 +379,35 @@ NonOverlappingRectanglesEnergyPropagator::FindConflict(
385
379
int opp_problem_size = 0 ;
386
380
// Also try the DFF on known conflicts, hopefully we will get a smaller
387
381
// explanation.
388
- std::vector<Rectangle> filtered_rectangles;
389
- filtered_rectangles.reserve (
390
- rectangles_with_too_much_energy.conflicts .size () +
391
- rectangles_with_too_much_energy.candidates .size ());
392
- filtered_rectangles = rectangles_with_too_much_energy.conflicts ;
393
- // Our current DFF does nothing if all elements are smaller than half of the
394
- // size of the rectangle. So we filter all rectangles that are twice the
395
- // dimensions of the largest item of our problem.
396
- for (const Rectangle& r : rectangles_with_too_much_energy.candidates ) {
397
- if (r.SizeX () <= 2 * max_x_item_size || r.SizeY () <= 2 * max_y_item_size) {
398
- filtered_rectangles.push_back (r);
399
- }
400
- }
401
382
// Sample 10 rectangles for looking for a conflict with DFF. This avoids
402
383
// making this heuristic too costly.
403
384
constexpr int kSampleSize = 10 ;
404
385
absl::InlinedVector<Rectangle, kSampleSize > sampled_rectangles;
405
- std::sample (filtered_rectangles.begin (), filtered_rectangles.end (),
406
- std::back_inserter (sampled_rectangles), kSampleSize , *random_);
386
+ std::sample (rectangles_with_too_much_energy.conflicts .begin (),
387
+ rectangles_with_too_much_energy.conflicts .end (),
388
+ std::back_inserter (sampled_rectangles), 5 , *random_);
389
+ std::sample (rectangles_with_too_much_energy.candidates .begin (),
390
+ rectangles_with_too_much_energy.candidates .end (),
391
+ std::back_inserter (sampled_rectangles),
392
+ kSampleSize - sampled_rectangles.size (), *random_);
393
+ std::sort (sampled_rectangles.begin (), sampled_rectangles.end (),
394
+ [](const Rectangle& a, const Rectangle& b) {
395
+ const bool larger = std::make_pair (a.SizeX (), a.SizeY ()) >
396
+ std::make_pair (b.SizeX (), b.SizeY ());
397
+ // Double-check the invariant from
398
+ // FindRectanglesWithEnergyConflictMC() that given two returned
399
+ // rectangles there is one that is fully inside the other.
400
+ if (larger) {
401
+ // Rectangle b is fully contained inside a
402
+ DCHECK (a.x_min <= b.x_min && a.x_max >= b.x_max &&
403
+ a.y_min <= b.y_min && a.y_max >= b.y_max );
404
+ } else {
405
+ // Rectangle a is fully contained inside b
406
+ DCHECK (a.x_min >= b.x_min && a.x_max <= b.x_max &&
407
+ a.y_min >= b.y_min && a.y_max <= b.y_max );
408
+ }
409
+ return larger;
410
+ });
407
411
std::vector<IntegerValue> sizes_x, sizes_y;
408
412
sizes_x.reserve (active_box_ranges.size ());
409
413
sizes_y.reserve (active_box_ranges.size ());
0 commit comments