135 if (!helper_.SynchronizeAndSetDirection(
136 x_is_forward_after_swap_, y_is_forward_after_swap_, swap_x_and_y_)) {
142 PopulateActiveBoxRanges();
166 potential_x_positions_.clear();
167 potential_y_positions_.clear();
170 potential_x_positions_.push_back(mandatory_region.
x_max);
171 potential_y_positions_.push_back(mandatory_region.
y_max);
177 std::vector<std::pair<int, std::optional<IntegerValue>>> found_propagations;
192 bool placed_at_x_min =
false;
195 potential_y_positions_.begin();
196 for (
int j = y_start; j < potential_y_positions_.size(); ++j) {
202 placed_at_x_min =
true;
205 .y_min = potential_y_positions_[j],
206 .y_max = potential_y_positions_[j] + box.
y_size};
211 if (placed_at_x_min)
continue;
218 std::optional<IntegerValue> new_x_min = std::nullopt;
219 for (
int j = 0; j < potential_x_positions_.size(); ++j) {
227 new_x_min = potential_x_positions_[j];
230 for (
int k = y_start; k < potential_y_positions_.size(); ++k) {
231 const IntegerValue potential_y_position = potential_y_positions_[k];
235 if (CanPlace(
i, {potential_x_positions_[j], potential_y_position})) {
238 new_x_min = potential_x_positions_[j];
242 if (new_x_min.has_value()) {
246 found_propagations.push_back({
i, new_x_min});
253 int box_index, IntegerValue new_x_min) {
269 potential_y_positions_.begin();
270 conflicts_per_x_and_y_.clear();
272 &conflicts_per_x_and_y_));
273 for (
int j = y_start; j < potential_y_positions_.size(); ++j) {
278 CHECK(!CanPlace(box_index,
280 &conflicts_per_x_and_y_));
282 for (
int j = 0; j < potential_x_positions_.size(); ++j) {
286 if (potential_x_positions_[j] >= new_x_min) {
289 CHECK(!CanPlace(box_index,
291 &conflicts_per_x_and_y_));
292 for (
int k = y_start; k < potential_y_positions_.size(); ++k) {
293 const IntegerValue potential_y_position = potential_y_positions_[k];
297 CHECK(!CanPlace(box_index,
298 {potential_x_positions_[j], potential_y_position},
299 &conflicts_per_x_and_y_));
307 std::vector<std::vector<int>> conflicting_position_per_box(
309 for (
int i = 0;
i < conflicts_per_x_and_y_.size(); ++
i) {
310 DCHECK(!conflicts_per_x_and_y_[
i].empty());
311 for (
const int j : conflicts_per_x_and_y_[
i]) {
312 conflicting_position_per_box[j].push_back(
i);
316 for (
const auto& conflicts : conflicting_position_per_box) {
317 if (conflicts.empty())
continue;
319 for (
const int i : conflicts) {
334 std::vector<int> boxes_participating_in_propagation;
335 boxes_participating_in_propagation.reserve(model.
num_subsets() + 1);
336 boxes_participating_in_propagation.push_back(box_index);
337 for (
int i = 0;
i < conflicting_position_per_box.size(); ++
i) {
338 const auto& conflicts = conflicting_position_per_box[
i];
339 if (conflicts.empty())
continue;
341 boxes_participating_in_propagation.push_back(
i);
345 VLOG_EVERY_N_SEC(3, 2) <<
"Found no_overlap_2d constraint propagation with "
346 << boxes_participating_in_propagation.size() <<
"/"
355 return boxes_participating_in_propagation;
359 const std::vector<std::pair<
int, std::optional<IntegerValue>>>&
360 found_propagations) {
361 for (
const auto& [box_index, new_x_min] : found_propagations) {
363 helper_.ClearReason();
365 const std::vector<int> minimum_problem_with_propagator =
367 box_index, new_x_min.has_value()
370 for (
const int j : minimum_problem_with_propagator) {
382 if (j != box_index || !new_x_min.has_value()) {
385 helper_.AddLeftMaxReason(
388 helper_.AddBottomMaxReason(
391 helper_.AddSizeMinReason(
b);
392 helper_.AddPresenceReason(
b);
394 if (new_x_min.has_value()) {
396 if (!helper_.IncreaseLeftMin(box_index, *new_x_min)) {
401 return helper_.ReportConflict();