139 if (!helper_.SynchronizeAndSetDirection(
140 x_is_forward_after_swap_, y_is_forward_after_swap_, swap_x_and_y_)) {
146 PopulateActiveBoxRanges();
158 for (
int i = 0;
i < num_active_ranges;
i++) {
172 potential_x_positions_.clear();
173 potential_y_positions_.clear();
176 potential_x_positions_.push_back(mandatory_region.
x_max);
177 potential_y_positions_.push_back(mandatory_region.
y_max);
183 std::vector<std::pair<int, std::optional<IntegerValue>>> found_propagations;
198 bool placed_at_x_min =
false;
201 potential_y_positions_.begin();
202 for (
int j = y_start; j < potential_y_positions_.size(); ++j) {
208 placed_at_x_min =
true;
211 .y_min = potential_y_positions_[j],
212 .y_max = potential_y_positions_[j] + box.
y_size};
217 if (placed_at_x_min)
continue;
224 std::optional<IntegerValue> new_x_min = std::nullopt;
225 for (
int j = 0; j < potential_x_positions_.size(); ++j) {
233 new_x_min = potential_x_positions_[j];
236 for (
int k = y_start; k < potential_y_positions_.size(); ++k) {
237 const IntegerValue potential_y_position = potential_y_positions_[k];
241 if (CanPlace(
i, {potential_x_positions_[j], potential_y_position})) {
244 new_x_min = potential_x_positions_[j];
248 if (new_x_min.has_value()) {
252 found_propagations.push_back({
i, new_x_min});
259 int box_index, IntegerValue new_x_min) {
275 potential_y_positions_.begin();
276 conflicts_per_x_and_y_.clear();
278 &conflicts_per_x_and_y_));
279 for (
int j = y_start; j < potential_y_positions_.size(); ++j) {
284 CHECK(!CanPlace(box_index,
286 &conflicts_per_x_and_y_));
288 for (
int j = 0; j < potential_x_positions_.size(); ++j) {
292 if (potential_x_positions_[j] >= new_x_min) {
295 CHECK(!CanPlace(box_index,
297 &conflicts_per_x_and_y_));
298 for (
int k = y_start; k < potential_y_positions_.size(); ++k) {
299 const IntegerValue potential_y_position = potential_y_positions_[k];
303 CHECK(!CanPlace(box_index,
304 {potential_x_positions_[j], potential_y_position},
305 &conflicts_per_x_and_y_));
313 std::vector<std::vector<int>> conflicting_position_per_box(
315 for (
int i = 0;
i < conflicts_per_x_and_y_.size(); ++
i) {
316 DCHECK(!conflicts_per_x_and_y_[
i].empty());
317 for (
const int j : conflicts_per_x_and_y_[
i]) {
318 conflicting_position_per_box[j].push_back(
i);
322 for (
const auto& conflicts : conflicting_position_per_box) {
323 if (conflicts.empty())
continue;
325 for (
const int i : conflicts) {
335 GuidedLocalSearch search(&inv);
336 CHECK(search.SetMaxIterations(100).NextSolution());
342 std::vector<int> boxes_participating_in_propagation;
343 boxes_participating_in_propagation.reserve(model.
num_subsets() + 1);
344 boxes_participating_in_propagation.push_back(box_index);
345 for (
int i = 0;
i < conflicting_position_per_box.size(); ++
i) {
346 const auto& conflicts = conflicting_position_per_box[
i];
347 if (conflicts.empty())
continue;
349 boxes_participating_in_propagation.push_back(
i);
353 VLOG_EVERY_N_SEC(3, 2) <<
"Found no_overlap_2d constraint propagation with "
354 << boxes_participating_in_propagation.size() <<
"/"
363 return boxes_participating_in_propagation;
367 const std::vector<std::pair<
int, std::optional<IntegerValue>>>&
368 found_propagations) {
369 for (
const auto& [box_index, new_x_min] : found_propagations) {
371 helper_.ClearReason();
373 const std::vector<int> minimum_problem_with_propagator =
375 box_index, new_x_min.has_value()
378 for (
const int j : minimum_problem_with_propagator) {
390 if (j != box_index || !new_x_min.has_value()) {
393 helper_.AddLeftMaxReason(
396 helper_.AddBottomMaxReason(
399 helper_.AddSizeMinReason(
b);
400 helper_.AddPresenceReason(
b);
402 if (new_x_min.has_value()) {
404 if (!helper_.IncreaseLeftMin(box_index, *new_x_min)) {
409 return helper_.ReportConflict();