OR-Tools  9.3
diffn.h
Go to the documentation of this file.
1// Copyright 2010-2021 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
14#ifndef OR_TOOLS_SAT_DIFFN_H_
15#define OR_TOOLS_SAT_DIFFN_H_
16
17#include <functional>
18#include <vector>
19
20#include "absl/container/flat_hash_set.h"
21#include "absl/types/span.h"
24#include "ortools/base/macros.h"
27#include "ortools/sat/integer.h"
29#include "ortools/sat/model.h"
31#include "ortools/sat/util.h"
33
34namespace operations_research {
35namespace sat {
36
37// Propagates using a box energy reasoning.
39 public:
40 // The strict parameters indicates how to place zero width or zero height
41 // boxes. If strict is true, these boxes must not 'cross' another box, and are
42 // pushed by the other boxes.
45 Model* model)
46 : x_(*x), y_(*y), random_(model->GetOrCreate<ModelRandomGenerator>()) {}
48
49 bool Propagate() final;
51
52 private:
53 void SortBoxesIntoNeighbors(int box, absl::Span<const int> local_boxes,
54 IntegerValue total_sum_of_areas);
55 bool FailWhenEnergyIsTooLarge(int box, absl::Span<const int> local_boxes,
56 IntegerValue total_sum_of_areas);
57
60 ModelRandomGenerator* random_;
61
62 // When the size of the bounding box is greater than any of the corresponding
63 // rectangles, then there is no point checking for overload.
64 IntegerValue threshold_x_;
65 IntegerValue threshold_y_;
66
67 std::vector<int> active_boxes_;
68 std::vector<IntegerValue> cached_energies_;
69 std::vector<Rectangle> cached_rectangles_;
70
71 struct Neighbor {
72 int box;
73 IntegerValue distance_to_bounding_box;
74 bool operator<(const Neighbor& o) const {
75 return distance_to_bounding_box < o.distance_to_bounding_box;
76 }
77 };
78 std::vector<Neighbor> neighbors_;
79
84};
85
86// Non overlapping rectangles.
88 : public PropagatorInterface {
89 public:
90 // The strict parameters indicates how to place zero width or zero height
91 // boxes. If strict is true, these boxes must not 'cross' another box, and are
92 // pushed by the other boxes.
93 // The slow_propagators select which disjunctive algorithms to propagate.
97 Model* model);
99
100 bool Propagate() final;
101 void Register(int fast_priority, int slow_priority);
102
103 private:
104 bool PropagateTwoBoxes();
105 bool FindBoxesThatMustOverlapAHorizontalLineAndPropagate(
106 bool fast_propagation, const SchedulingConstraintHelper& x,
108
112 const bool strict_;
113
114 GenericLiteralWatcher* watcher_;
115 int fast_id_; // Propagator id of the "fast" version.
116
117 std::vector<IndexedInterval> indexed_intervals_;
118 std::vector<std::vector<int>> events_overlapping_boxes_;
119
120 absl::flat_hash_set<absl::Span<int>> reduced_overlapping_boxes_;
121 std::vector<absl::Span<int>> boxes_to_propagate_;
122 std::vector<absl::Span<int>> disjoint_boxes_;
123
124 DisjunctiveOverloadChecker overload_checker_;
125 DisjunctiveDetectablePrecedences forward_detectable_precedences_;
126 DisjunctiveDetectablePrecedences backward_detectable_precedences_;
127 DisjunctiveNotLast forward_not_last_;
128 DisjunctiveNotLast backward_not_last_;
129 DisjunctiveEdgeFinding forward_edge_finding_;
130 DisjunctiveEdgeFinding backward_edge_finding_;
131
136};
137
138// Add a cumulative relaxation. That is, on one dimension, it does not enforce
139// the rectangle aspect, allowing vertical slices to move freely.
141 const std::vector<IntervalVariable>& x_intervals,
143
144// Enforces that the boxes with corners in (x, y), (x + dx, y), (x, y + dy)
145// and (x + dx, y + dy) do not overlap.
146// If strict is true, and if one box has a zero dimension, it still cannot
147// intersect another box.
148inline std::function<void(Model*)> NonOverlappingRectangles(
149 const std::vector<IntervalVariable>& x,
150 const std::vector<IntervalVariable>& y, bool is_strict,
151 bool add_cumulative_relaxation = true) {
152 return [=](Model* model) {
157 model->TakeOwnership(x_helper);
158 model->TakeOwnership(y_helper);
159
161 new NonOverlappingRectanglesEnergyPropagator(x_helper, y_helper, model);
162 GenericLiteralWatcher* const watcher =
163 model->GetOrCreate<GenericLiteralWatcher>();
164 watcher->SetPropagatorPriority(energy_constraint->RegisterWith(watcher), 3);
165 model->TakeOwnership(energy_constraint);
166
168 new NonOverlappingRectanglesDisjunctivePropagator(is_strict, x_helper,
169 y_helper, model);
170 constraint->Register(/*fast_priority=*/3, /*slow_priority=*/4);
171 model->TakeOwnership(constraint);
172
173 if (add_cumulative_relaxation) {
174 // We must first check if the cumulative relaxation is possible.
175 bool some_boxes_are_only_optional_on_x = false;
176 bool some_boxes_are_only_optional_on_y = false;
177 for (int i = 0; i < x.size(); ++i) {
178 if (x_helper->IsOptional(i) && y_helper->IsOptional(i) &&
179 x_helper->PresenceLiteral(i) != y_helper->PresenceLiteral(i)) {
180 // Abort as the task would be conditioned by two literals.
181 return;
182 }
183 if (x_helper->IsOptional(i) && !y_helper->IsOptional(i)) {
184 // We cannot use x_size as the demand of the cumulative based on
185 // the y_intervals.
186 some_boxes_are_only_optional_on_x = true;
187 }
188 if (y_helper->IsOptional(i) && !x_helper->IsOptional(i)) {
189 // We cannot use y_size as the demand of the cumulative based on
190 // the y_intervals.
191 some_boxes_are_only_optional_on_y = true;
192 }
193 }
194 if (!some_boxes_are_only_optional_on_y) {
195 AddDiffnCumulativeRelationOnX(x, x_helper, y_helper, model);
196 }
197 if (!some_boxes_are_only_optional_on_x) {
198 AddDiffnCumulativeRelationOnX(y, y_helper, x_helper, model);
199 }
200 }
201 };
202}
203
204} // namespace sat
205} // namespace operations_research
206
207#endif // OR_TOOLS_SAT_DIFFN_H_
void SetPropagatorPriority(int id, int priority)
Definition: integer.cc:2051
Class that owns everything related to a particular optimization model.
Definition: sat/model.h:42
NonOverlappingRectanglesDisjunctivePropagator(bool strict, SchedulingConstraintHelper *x, SchedulingConstraintHelper *y, Model *model)
Definition: sat/diffn.cc:388
NonOverlappingRectanglesEnergyPropagator(SchedulingConstraintHelper *x, SchedulingConstraintHelper *y, Model *model)
Definition: diffn.h:43
GRBmodel * model
Definition: cleanup.h:22
void AddDiffnCumulativeRelationOnX(const std::vector< IntervalVariable > &x_intervals, SchedulingConstraintHelper *x, SchedulingConstraintHelper *y, Model *model)
Definition: sat/diffn.cc:87
std::function< void(Model *)> NonOverlappingRectangles(const std::vector< IntervalVariable > &x, const std::vector< IntervalVariable > &y, bool is_strict, bool add_cumulative_relaxation=true)
Definition: diffn.h:148
Collection of objects used to extend the Constraint Solver library.
STL namespace.