OR-Tools  9.3
diffn_util.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_UTIL_H_
15#define OR_TOOLS_SAT_DIFFN_UTIL_H_
16
17#include <algorithm>
18#include <cstdint>
19#include <iosfwd>
20#include <string>
21#include <tuple>
22#include <vector>
23
24#include "absl/container/flat_hash_set.h"
25#include "absl/random/bit_gen_ref.h"
26#include "absl/strings/str_format.h"
27#include "absl/types/span.h"
29#include "ortools/sat/integer.h"
32
33namespace operations_research {
34namespace sat {
35
36struct Rectangle {
37 IntegerValue x_min;
38 IntegerValue x_max;
39 IntegerValue y_min;
40 IntegerValue y_max;
41
42 void TakeUnionWith(const Rectangle& other) {
43 x_min = std::min(x_min, other.x_min);
44 y_min = std::min(y_min, other.y_min);
45 x_max = std::max(x_max, other.x_max);
46 y_max = std::max(y_max, other.y_max);
47 }
48
49 IntegerValue Area() const { return (x_max - x_min) * (y_max - y_min); }
50
51 bool IsDisjoint(const Rectangle& other) const;
52
53 std::string DebugString() const {
54 return absl::StrFormat("rectangle(x(%i..%i), y(%i..%i))", x_min.value(),
55 x_max.value(), y_min.value(), y_max.value());
56 }
57};
58
59// Creates a graph when two nodes are connected iif their rectangles overlap.
60// Then partition into connected components.
61//
62// This method removes all singleton components. It will modify the
63// active_rectangle span in place.
64std::vector<absl::Span<int>> GetOverlappingRectangleComponents(
65 const std::vector<Rectangle>& rectangles,
66 absl::Span<int> active_rectangles);
67
68// Visible for testing. The algo is in O(n^4) so shouldn't be used directly.
69// Returns true if there exist a bounding box with too much energy.
70bool BoxesAreInEnergyConflict(const std::vector<Rectangle>& rectangles,
71 const std::vector<IntegerValue>& energies,
72 absl::Span<const int> boxes,
73 Rectangle* conflict = nullptr);
74
75// Checks that there is indeed a conflict for the given bounding_box and
76// report it. This returns false for convenience as we usually want to return
77// false on a conflict.
78//
79// TODO(user): relax the bounding box dimension to have a relaxed explanation.
80// We can also minimize the number of required intervals.
81bool ReportEnergyConflict(Rectangle bounding_box, absl::Span<const int> boxes,
82 SchedulingConstraintHelper* x,
83 SchedulingConstraintHelper* y);
84
85// A O(n^2) algorithm to analyze all the relevant X intervals and infer a
86// threshold of the y size of a bounding box after which there is no point
87// checking for energy overload.
88//
89// Returns false on conflict, and fill the bounding box that caused the
90// conflict.
91//
92// If transpose is true, we analyze the relevant Y intervals instead.
93bool AnalyzeIntervals(bool transpose, absl::Span<const int> boxes,
94 const std::vector<Rectangle>& rectangles,
95 const std::vector<IntegerValue>& rectangle_energies,
96 IntegerValue* x_threshold, IntegerValue* y_threshold,
97 Rectangle* conflict = nullptr);
98
99// Removes boxes with a size above the thresholds. Also randomize the order.
100// Because we rely on various heuristic, this allow to change the order from
101// one call to the next.
102absl::Span<int> FilterBoxesAndRandomize(
103 const std::vector<Rectangle>& cached_rectangles, absl::Span<int> boxes,
104 IntegerValue threshold_x, IntegerValue threshold_y, absl::BitGenRef random);
105
106// Given the total energy of all rectangles (sum of energies[box]) we know that
107// any box with an area greater than that cannot participate in any "bounding
108// box" conflict. As we remove this box, the total energy decrease, so we might
109// remove more. This works in O(n log n).
110absl::Span<int> FilterBoxesThatAreTooLarge(
111 const std::vector<Rectangle>& cached_rectangles,
112 const std::vector<IntegerValue>& energies, absl::Span<int> boxes);
113
115 int index;
116 IntegerValue start;
117 IntegerValue end;
118
119 bool operator==(const IndexedInterval& rhs) const {
120 return std::tie(start, end, index) ==
121 std::tie(rhs.start, rhs.end, rhs.index);
122 }
123
124 // NOTE(user): We would like to use TUPLE_DEFINE_STRUCT, but sadly it doesn't
125 // support //buildenv/target:non_prod.
127 bool operator()(const IndexedInterval& a, const IndexedInterval& b) const {
128 return std::tie(a.start, a.end, a.index) <
129 std::tie(b.start, b.end, b.index);
130 }
131 };
133 bool operator()(const IndexedInterval& a, const IndexedInterval& b) const {
134 return a.start < b.start;
135 }
136 };
137};
138std::ostream& operator<<(std::ostream& out, const IndexedInterval& interval);
139
140// Given n fixed intervals, returns the subsets of intervals that overlap during
141// at least one time unit. Note that we only return "maximal" subset and filter
142// subset strictly included in another.
143//
144// All Intervals must have a positive size.
145//
146// The algo is in O(n log n) + O(result_size) which is usually O(n^2).
147void ConstructOverlappingSets(bool already_sorted,
148 std::vector<IndexedInterval>* intervals,
149 std::vector<std::vector<int>>* result);
150
151// Given n intervals, returns the set of connected components (using the overlap
152// relation between 2 intervals). Components are sorted by their start, and
153// inside a component, the intervals are also sorted by start.
154// `intervals` is only sorted (by start), and not modified otherwise.
156 std::vector<IndexedInterval>* intervals,
157 std::vector<std::vector<int>>* components);
158
159// Similar to GetOverlappingIntervalComponents(), but returns the indices of
160// all intervals whose removal would create one more connected component in the
161// interval graph. Those are sorted by start. See:
162// https://en.wikipedia.org/wiki/Glossary_of_graph_theory#articulation_point.
163std::vector<int> GetIntervalArticulationPoints(
164 std::vector<IndexedInterval>* intervals);
165
166// This class is used by the no_overlap_2d constraint to maintain the envelope
167// of a set of rectangles. This envelope is not the convex hull, but the exact
168// polyline (aligned with the x and y axis) that contains all the rectangles
169// passed with the AddRectangle() call.
171 public:
172 // Simple start of a rectangle. This is used to represent the residual
173 // capacity profile.
174 struct Rectangle {
175 Rectangle(IntegerValue start, IntegerValue height)
176 : start(start), height(height) {}
177
178 bool operator<(const Rectangle& other) const { return start < other.start; }
179 bool operator==(const Rectangle& other) const {
180 return start == other.start && height == other.height;
181 }
182
183 IntegerValue start = IntegerValue(0);
184 IntegerValue height = IntegerValue(0);
185 };
186
187 void Clear();
188
189 // Adds a rectangle to the current shape.
190 void AddRectangle(IntegerValue x_min, IntegerValue x_max, IntegerValue y_min,
191 IntegerValue y_max);
192
193 // Adds a mandatory profile consumption. All mandatory usages will be
194 // subtracted from the y_max-y_min profile to build the residual capacity.
195 void AddMandatoryConsumption(IntegerValue x_min, IntegerValue x_max,
196 IntegerValue y_height);
197
198 // Returns the profile of the function:
199 // capacity(x) = max(y_max of rectangles overlapping x) - min(y_min of
200 // rectangle overlapping x) - sum(y_height of mandatory rectangles
201 // overlapping x) where a rectangle overlaps x if x_min <= x < x_max.
202 //
203 // Note the profile can contain negative heights in case the mandatory part
204 // exceeds the range on the y axis.
205 //
206 // Note that it adds a sentinel (kMinIntegerValue, 0) at the start. It is
207 // useful when we reverse the direction on the x axis.
208 void BuildResidualCapacityProfile(std::vector<Rectangle>* result);
209
210 // Returns the exact area of the bounding polyline of all rectangles added.
211 //
212 // Note that this will redo the computation each time.
213 IntegerValue GetBoundingArea();
214
215 private:
216 // Type for the capacity events.
217 enum EventType { START_RECTANGLE, END_RECTANGLE, CHANGE_MANDATORY_PROFILE };
218
219 // Individual events.
220 struct Event {
221 IntegerValue time;
222 IntegerValue y_min;
223 IntegerValue y_max;
224 EventType type;
225 int index;
226
227 const bool operator<(const Event& other) const { return time < other.time; }
228 };
229
230 // Element of the integer_pq heap.
231 struct QueueElement {
232 int Index() const { return index; }
233 const bool operator<(const QueueElement& o) const {
234 return value < o.value;
235 }
236
237 int index;
238 IntegerValue value;
239 };
240
241 static Event StartRectangleEvent(int index, IntegerValue x_min,
242 IntegerValue y_min, IntegerValue y_max) {
243 return {x_min, y_min, y_max, START_RECTANGLE, index};
244 }
245
246 static Event EndRectangleEvent(int index, IntegerValue x_max) {
247 return {x_max, kMinIntegerValue, kMinIntegerValue, END_RECTANGLE, index};
248 }
249
250 static Event ChangeMandatoryProfileEvent(IntegerValue x, IntegerValue delta) {
251 return {x, /*y_min=*/delta, /*y_max=*/kMinIntegerValue,
252 CHANGE_MANDATORY_PROFILE, /*index=*/-1};
253 }
254
255 std::vector<Event> events_;
256 int num_rectangles_added_ = 0;
257};
258
259} // namespace sat
260} // namespace operations_research
261
262#endif // OR_TOOLS_SAT_DIFFN_UTIL_H_
int64_t max
Definition: alldiff_cst.cc:140
int64_t min
Definition: alldiff_cst.cc:139
void AddMandatoryConsumption(IntegerValue x_min, IntegerValue x_max, IntegerValue y_height)
Definition: diffn_util.cc:506
void AddRectangle(IntegerValue x_min, IntegerValue x_max, IntegerValue y_min, IntegerValue y_max)
Definition: diffn_util.cc:495
void BuildResidualCapacityProfile(std::vector< Rectangle > *result)
Definition: diffn_util.cc:516
int64_t b
int64_t a
int64_t value
int index
std::ostream & operator<<(std::ostream &os, const BoolVar &var)
Definition: cp_model.cc:89
void GetOverlappingIntervalComponents(std::vector< IndexedInterval > *intervals, std::vector< std::vector< int > > *components)
Definition: diffn_util.cc:409
std::vector< int > GetIntervalArticulationPoints(std::vector< IndexedInterval > *intervals)
Definition: diffn_util.cc:442
std::vector< absl::Span< int > > GetOverlappingRectangleComponents(const std::vector< Rectangle > &rectangles, absl::Span< int > active_rectangles)
Definition: diffn_util.cc:40
absl::Span< int > FilterBoxesAndRandomize(const std::vector< Rectangle > &cached_rectangles, absl::Span< int > boxes, IntegerValue threshold_x, IntegerValue threshold_y, absl::BitGenRef random)
Definition: diffn_util.cc:317
constexpr IntegerValue kMinIntegerValue(-kMaxIntegerValue.value())
bool AnalyzeIntervals(bool transpose, absl::Span< const int > local_boxes, const std::vector< Rectangle > &rectangles, const std::vector< IntegerValue > &rectangle_energies, IntegerValue *x_threshold, IntegerValue *y_threshold, Rectangle *conflict)
Definition: diffn_util.cc:165
bool ReportEnergyConflict(Rectangle bounding_box, absl::Span< const int > boxes, SchedulingConstraintHelper *x, SchedulingConstraintHelper *y)
Definition: diffn_util.cc:66
void ConstructOverlappingSets(bool already_sorted, std::vector< IndexedInterval > *intervals, std::vector< std::vector< int > > *result)
Definition: diffn_util.cc:360
bool BoxesAreInEnergyConflict(const std::vector< Rectangle > &rectangles, const std::vector< IntegerValue > &energies, absl::Span< const int > boxes, Rectangle *conflict)
Definition: diffn_util.cc:98
absl::Span< int > FilterBoxesThatAreTooLarge(const std::vector< Rectangle > &cached_rectangles, const std::vector< IntegerValue > &energies, absl::Span< int > boxes)
Definition: diffn_util.cc:333
Collection of objects used to extend the Constraint Solver library.
int64_t time
Definition: resource.cc:1693
int64_t delta
Definition: resource.cc:1694
IntervalVar * interval
Definition: resource.cc:100
bool operator<(const Rectangle &other) const
Definition: diffn_util.h:178
bool operator==(const Rectangle &other) const
Definition: diffn_util.h:179
Rectangle(IntegerValue start, IntegerValue height)
Definition: diffn_util.h:175
bool operator()(const IndexedInterval &a, const IndexedInterval &b) const
Definition: diffn_util.h:133
bool operator()(const IndexedInterval &a, const IndexedInterval &b) const
Definition: diffn_util.h:127
bool operator==(const IndexedInterval &rhs) const
Definition: diffn_util.h:119
std::string DebugString() const
Definition: diffn_util.h:53
void TakeUnionWith(const Rectangle &other)
Definition: diffn_util.h:42
bool IsDisjoint(const Rectangle &other) const
Definition: diffn_util.cc:35