OR-Tools  9.1
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 <vector>
18
22#include "ortools/base/macros.h"
25#include "ortools/sat/integer.h"
27#include "ortools/sat/model.h"
29
30namespace operations_research {
31namespace sat {
32
33// Propagates using a box energy reasoning.
35 public:
36 // The strict parameters indicates how to place zero width or zero height
37 // boxes. If strict is true, these boxes must not 'cross' another box, and are
38 // pushed by the other boxes.
41 Model* model)
42 : x_(*x), y_(*y), random_(model->GetOrCreate<ModelRandomGenerator>()) {}
44
45 bool Propagate() final;
47
48 private:
49 void SortBoxesIntoNeighbors(int box, absl::Span<const int> local_boxes,
50 IntegerValue total_sum_of_areas);
51 bool FailWhenEnergyIsTooLarge(int box, absl::Span<const int> local_boxes,
52 IntegerValue total_sum_of_areas);
53
56 ModelRandomGenerator* random_;
57
58 // When the size of the bounding box is greater than any of the corresponding
59 // rectangles, then there is no point checking for overload.
60 IntegerValue threshold_x_;
61 IntegerValue threshold_y_;
62
63 std::vector<int> active_boxes_;
64 std::vector<IntegerValue> cached_energies_;
65 std::vector<Rectangle> cached_rectangles_;
66
67 struct Neighbor {
68 int box;
69 IntegerValue distance_to_bounding_box;
70 bool operator<(const Neighbor& o) const {
71 return distance_to_bounding_box < o.distance_to_bounding_box;
72 }
73 };
74 std::vector<Neighbor> neighbors_;
75
80};
81
82// Non overlapping rectangles.
84 : public PropagatorInterface {
85 public:
86 // The strict parameters indicates how to place zero width or zero height
87 // boxes. If strict is true, these boxes must not 'cross' another box, and are
88 // pushed by the other boxes.
89 // The slow_propagators select which disjunctive algorithms to propagate.
93 Model* model);
95
96 bool Propagate() final;
97 void Register(int fast_priority, int slow_priority);
98
99 private:
100 bool PropagateTwoBoxes();
101 bool FindBoxesThatMustOverlapAHorizontalLineAndPropagate(
103 std::function<bool()> inner_propagate);
104
108 const bool strict_;
109
110 GenericLiteralWatcher* watcher_;
111 int fast_id_; // Propagator id of the "fast" version.
112
113 std::vector<IndexedInterval> indexed_intervals_;
114 std::vector<std::vector<int>> events_overlapping_boxes_;
115
116 absl::flat_hash_set<absl::Span<int>> reduced_overlapping_boxes_;
117 std::vector<absl::Span<int>> boxes_to_propagate_;
118 std::vector<absl::Span<int>> disjoint_boxes_;
119
120 DisjunctiveOverloadChecker overload_checker_;
121 DisjunctiveDetectablePrecedences forward_detectable_precedences_;
122 DisjunctiveDetectablePrecedences backward_detectable_precedences_;
123 DisjunctiveNotLast forward_not_last_;
124 DisjunctiveNotLast backward_not_last_;
125 DisjunctiveEdgeFinding forward_edge_finding_;
126 DisjunctiveEdgeFinding backward_edge_finding_;
127
132};
133
134// Add a cumulative relaxation. That is, on one dimension, it does not enforce
135// the rectangle aspect, allowing vertical slices to move freely.
136void AddCumulativeRelaxation(const std::vector<IntervalVariable>& x_intervals,
139
140// Enforces that the boxes with corners in (x, y), (x + dx, y), (x, y + dy)
141// and (x + dx, y + dy) do not overlap.
142// If strict is true, and if one box has a zero dimension, it still cannot
143// intersect another box.
144inline std::function<void(Model*)> NonOverlappingRectangles(
145 const std::vector<IntervalVariable>& x,
146 const std::vector<IntervalVariable>& y, bool is_strict,
147 bool add_cumulative_relaxation = true) {
148 return [=](Model* model) {
153 model->TakeOwnership(x_helper);
154 model->TakeOwnership(y_helper);
155
157 new NonOverlappingRectanglesEnergyPropagator(x_helper, y_helper, model);
158 GenericLiteralWatcher* const watcher =
159 model->GetOrCreate<GenericLiteralWatcher>();
160 watcher->SetPropagatorPriority(energy_constraint->RegisterWith(watcher), 3);
161 model->TakeOwnership(energy_constraint);
162
164 new NonOverlappingRectanglesDisjunctivePropagator(is_strict, x_helper,
165 y_helper, model);
166 constraint->Register(/*fast_priority=*/3, /*slow_priority=*/4);
167 model->TakeOwnership(constraint);
168
169 if (add_cumulative_relaxation) {
170 AddCumulativeRelaxation(x, x_helper, y_helper, model);
171 AddCumulativeRelaxation(y, y_helper, x_helper, model);
172 }
173 };
174}
175
176} // namespace sat
177} // namespace operations_research
178
179#endif // OR_TOOLS_SAT_DIFFN_H_
void SetPropagatorPriority(int id, int priority)
Definition: integer.cc:2019
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:330
NonOverlappingRectanglesEnergyPropagator(SchedulingConstraintHelper *x, SchedulingConstraintHelper *y, Model *model)
Definition: diffn.h:39
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:144
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.