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