Google OR-Tools v9.14
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
2d_mandatory_overlap_propagator.cc
Go to the documentation of this file.
1// Copyright 2010-2025 Google LLC
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
15
16#include <cstdint>
17#include <optional>
18#include <string>
19#include <utility>
20#include <vector>
21
22#include "absl/log/log.h"
23#include "absl/log/vlog_is_on.h"
24#include "absl/types/span.h"
26#include "ortools/sat/integer.h"
28#include "ortools/sat/model.h"
31
32namespace operations_research {
33namespace sat {
34
36 const int id = watcher->Register(this);
37 helper_.WatchAllBoxes(id);
38 return id;
39}
40
42 if (!VLOG_IS_ON(1)) return;
43 std::vector<std::pair<std::string, int64_t>> stats;
44 stats.push_back({"MandatoryOverlapPropagator/called_with_zero_area",
45 num_calls_zero_area_});
46 stats.push_back({"MandatoryOverlapPropagator/called_without_zero_area",
47 num_calls_nonzero_area_});
48 stats.push_back({"MandatoryOverlapPropagator/conflicts", num_conflicts_});
49
50 shared_stats_->AddStats(stats);
51}
52
54 if (!helper_.SynchronizeAndSetDirection()) return false;
55
56 mandatory_regions_.clear();
57 mandatory_regions_index_.clear();
58 bool has_zero_area_boxes = false;
59 absl::Span<const TaskTime> tasks =
60 helper_.x_helper().TaskByIncreasingNegatedStartMax();
61 for (int i = tasks.size(); --i >= 0;) {
62 const int b = tasks[i].task_index;
63 if (!helper_.IsPresent(b)) continue;
64
65 const IntegerValue x_start_max = helper_.x_helper().StartMax(b);
66 const IntegerValue x_end_min = helper_.x_helper().EndMin(b);
67 if (x_start_max > x_end_min) continue;
68
69 const IntegerValue y_start_max = helper_.y_helper().StartMax(b);
70 const IntegerValue y_end_min = helper_.y_helper().EndMin(b);
71 if (y_start_max > y_end_min) continue;
72
73 mandatory_regions_.push_back({.x_min = x_start_max,
74 .x_max = x_end_min,
75 .y_min = y_start_max,
76 .y_max = y_end_min});
77 mandatory_regions_index_.push_back(b);
78
79 if (mandatory_regions_.back().SizeX() == 0 ||
80 mandatory_regions_.back().SizeY() == 0) {
81 has_zero_area_boxes = true;
82 }
83 }
84 std::optional<std::pair<int, int>> conflict;
85 if (has_zero_area_boxes) {
86 num_calls_zero_area_++;
87 conflict = FindOneIntersectionIfPresentWithZeroArea(mandatory_regions_);
88 } else {
89 num_calls_nonzero_area_++;
90 conflict = FindOneIntersectionIfPresent(mandatory_regions_);
91 }
92
93 if (conflict.has_value()) {
94 num_conflicts_++;
95 return helper_.ReportConflictFromTwoBoxes(
96 mandatory_regions_index_[conflict->first],
97 mandatory_regions_index_[conflict->second]);
98 }
99 return true;
100}
101
103 NoOverlap2DConstraintHelper* helper, Model* model,
104 GenericLiteralWatcher* watcher, int priority) {
105 MandatoryOverlapPropagator* propagator =
106 new MandatoryOverlapPropagator(helper, model);
107 watcher->SetPropagatorPriority(propagator->RegisterWith(watcher), priority);
108 model->TakeOwnership(propagator);
109}
110
111} // namespace sat
112} // namespace operations_research
void SetPropagatorPriority(int id, int priority)
Definition integer.cc:2352
int Register(PropagatorInterface *propagator)
Registers a propagator and returns its unique ids.
Definition integer.cc:2326
std::optional< std::pair< int, int > > FindOneIntersectionIfPresent(absl::Span< const Rectangle > rectangles)
void CreateAndRegisterMandatoryOverlapPropagator(NoOverlap2DConstraintHelper *helper, Model *model, GenericLiteralWatcher *watcher, int priority)
std::optional< std::pair< int, int > > FindOneIntersectionIfPresentWithZeroArea(absl::Span< const Rectangle > rectangles)
In SWIG mode, we don't want anything besides these top-level includes.