Google OR-Tools v9.11
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
diffn_util.h
Go to the documentation of this file.
1// Copyright 2010-2024 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 <iosfwd>
19#include <limits>
20#include <optional>
21#include <ostream>
22#include <string>
23#include <tuple>
24#include <utility>
25#include <vector>
26
27#include "absl/container/flat_hash_set.h"
28#include "absl/container/inlined_vector.h"
29#include "absl/log/check.h"
30#include "absl/random/bit_gen_ref.h"
31#include "absl/strings/str_format.h"
32#include "absl/types/span.h"
33#include "ortools/sat/integer.h"
36
37namespace operations_research {
38namespace sat {
39
40struct Rectangle {
41 IntegerValue x_min;
42 IntegerValue x_max;
43 IntegerValue y_min;
44 IntegerValue y_max;
45
46 void GrowToInclude(const Rectangle& other) {
47 x_min = std::min(x_min, other.x_min);
48 y_min = std::min(y_min, other.y_min);
49 x_max = std::max(x_max, other.x_max);
50 y_max = std::max(y_max, other.y_max);
51 }
52
53 IntegerValue Area() const { return SizeX() * SizeY(); }
54
55 IntegerValue SizeX() const { return x_max - x_min; }
56 IntegerValue SizeY() const { return y_max - y_min; }
57
58 bool IsDisjoint(const Rectangle& other) const;
59
60 // Returns an empty rectangle if no intersection.
61 Rectangle Intersect(const Rectangle& other) const;
62 IntegerValue IntersectArea(const Rectangle& other) const;
63
64 // Returns `this \ other` as a set of disjoint rectangles of non-empty area.
65 // The resulting vector will have at most four elements.
66 absl::InlinedVector<Rectangle, 4> SetDifference(const Rectangle& other) const;
67
68 template <typename Sink>
69 friend void AbslStringify(Sink& sink, const Rectangle& r) {
70 absl::Format(&sink, "rectangle(x(%i..%i), y(%i..%i))", r.x_min.value(),
71 r.x_max.value(), r.y_min.value(), r.y_max.value());
72 }
73
74 bool operator==(const Rectangle& other) const {
75 return std::tie(x_min, x_max, y_min, y_max) ==
76 std::tie(other.x_min, other.x_max, other.y_min, other.y_max);
77 }
78
79 static Rectangle GetEmpty() {
80 return Rectangle{.x_min = IntegerValue(0),
81 .x_max = IntegerValue(0),
82 .y_min = IntegerValue(0),
83 .y_max = IntegerValue(0)};
84 }
85};
86
87inline Rectangle Rectangle::Intersect(const Rectangle& other) const {
88 const IntegerValue ret_x_min = std::max(x_min, other.x_min);
89 const IntegerValue ret_y_min = std::max(y_min, other.y_min);
90 const IntegerValue ret_x_max = std::min(x_max, other.x_max);
91 const IntegerValue ret_y_max = std::min(y_max, other.y_max);
92
93 if (ret_x_min >= ret_x_max || ret_y_min >= ret_y_max) {
94 return GetEmpty();
95 } else {
96 return Rectangle{.x_min = ret_x_min,
97 .x_max = ret_x_max,
98 .y_min = ret_y_min,
99 .y_max = ret_y_max};
100 }
101}
102
103inline IntegerValue Rectangle::IntersectArea(const Rectangle& other) const {
104 const IntegerValue ret_x_min = std::max(x_min, other.x_min);
105 const IntegerValue ret_y_min = std::max(y_min, other.y_min);
106 const IntegerValue ret_x_max = std::min(x_max, other.x_max);
107 const IntegerValue ret_y_max = std::min(y_max, other.y_max);
108
109 if (ret_x_min >= ret_x_max || ret_y_min >= ret_y_max) {
110 return 0;
111 } else {
112 return (ret_x_max - ret_x_min) * (ret_y_max - ret_y_min);
113 }
114}
115
116// Creates a graph when two nodes are connected iff their rectangles overlap.
117// Then partition into connected components.
118//
119// This method removes all singleton components. It will modify the
120// active_rectangle span in place.
121std::vector<absl::Span<int>> GetOverlappingRectangleComponents(
122 absl::Span<const Rectangle> rectangles, absl::Span<int> active_rectangles);
123
124// Visible for testing. The algo is in O(n^4) so shouldn't be used directly.
125// Returns true if there exist a bounding box with too much energy.
126bool BoxesAreInEnergyConflict(const std::vector<Rectangle>& rectangles,
127 const std::vector<IntegerValue>& energies,
128 absl::Span<const int> boxes,
129 Rectangle* conflict = nullptr);
130
131// Checks that there is indeed a conflict for the given bounding_box and
132// report it. This returns false for convenience as we usually want to return
133// false on a conflict.
134//
135// TODO(user): relax the bounding box dimension to have a relaxed explanation.
136// We can also minimize the number of required intervals.
137bool ReportEnergyConflict(Rectangle bounding_box, absl::Span<const int> boxes,
140
141// A O(n^2) algorithm to analyze all the relevant X intervals and infer a
142// threshold of the y size of a bounding box after which there is no point
143// checking for energy overload.
144//
145// Returns false on conflict, and fill the bounding box that caused the
146// conflict.
147//
148// If transpose is true, we analyze the relevant Y intervals instead.
149bool AnalyzeIntervals(bool transpose, absl::Span<const int> boxes,
150 absl::Span<const Rectangle> rectangles,
151 absl::Span<const IntegerValue> rectangle_energies,
152 IntegerValue* x_threshold, IntegerValue* y_threshold,
153 Rectangle* conflict = nullptr);
154
155// Removes boxes with a size above the thresholds. Also randomize the order.
156// Because we rely on various heuristic, this allow to change the order from
157// one call to the next.
158absl::Span<int> FilterBoxesAndRandomize(
159 absl::Span<const Rectangle> cached_rectangles, absl::Span<int> boxes,
160 IntegerValue threshold_x, IntegerValue threshold_y, absl::BitGenRef random);
161
162// Given the total energy of all rectangles (sum of energies[box]) we know that
163// any box with an area greater than that cannot participate in any "bounding
164// box" conflict. As we remove this box, the total energy decrease, so we might
165// remove more. This works in O(n log n).
166absl::Span<int> FilterBoxesThatAreTooLarge(
167 absl::Span<const Rectangle> cached_rectangles,
168 absl::Span<const IntegerValue> energies, absl::Span<int> boxes);
169
171 int index;
172 IntegerValue start;
173 IntegerValue end;
174
175 bool operator==(const IndexedInterval& rhs) const {
176 return std::tie(start, end, index) ==
177 std::tie(rhs.start, rhs.end, rhs.index);
178 }
179
180 // NOTE(user): We would like to use TUPLE_DEFINE_STRUCT, but sadly it doesn't
181 // support //buildenv/target:non_prod.
183 bool operator()(const IndexedInterval& a, const IndexedInterval& b) const {
184 return std::tie(a.start, a.end, a.index) <
185 std::tie(b.start, b.end, b.index);
186 }
187 };
189 bool operator()(const IndexedInterval& a, const IndexedInterval& b) const {
190 return a.start < b.start;
191 }
192 };
193};
194std::ostream& operator<<(std::ostream& out, const IndexedInterval& interval);
195
196// Given n fixed intervals, returns the subsets of intervals that overlap during
197// at least one time unit. Note that we only return "maximal" subset and filter
198// subset strictly included in another.
199//
200// All Intervals must have a positive size.
201//
202// The algo is in O(n log n) + O(result_size) which is usually O(n^2).
203void ConstructOverlappingSets(bool already_sorted,
204 std::vector<IndexedInterval>* intervals,
205 std::vector<std::vector<int>>* result);
206
207// Given n intervals, returns the set of connected components (using the overlap
208// relation between 2 intervals). Components are sorted by their start, and
209// inside a component, the intervals are also sorted by start.
210// `intervals` is only sorted (by start), and not modified otherwise.
212 std::vector<IndexedInterval>* intervals,
213 std::vector<std::vector<int>>* components);
214
215// Similar to GetOverlappingIntervalComponents(), but returns the indices of
216// all intervals whose removal would create one more connected component in the
217// interval graph. Those are sorted by start. See:
218// https://en.wikipedia.org/wiki/Glossary_of_graph_theory#articulation_point.
219std::vector<int> GetIntervalArticulationPoints(
220 std::vector<IndexedInterval>* intervals);
221
223 int index;
224 struct Interval {
225 IntegerValue start_min;
226 IntegerValue start_max;
227 IntegerValue end_min;
228 IntegerValue end_max;
229 };
232};
233
236 CONFLICT,
237 FIRST_BELOW_SECOND,
238 FIRST_ABOVE_SECOND,
239 FIRST_LEFT_OF_SECOND,
240 FIRST_RIGHT_OF_SECOND,
241 };
242
246
247 bool operator==(const PairwiseRestriction& rhs) const {
248 return first_index == rhs.first_index && second_index == rhs.second_index &&
249 type == rhs.type;
250 }
251};
252
253// Find pair of items that are either in conflict or could have their range
254// shrinked to avoid conflict.
256 absl::Span<const ItemForPairwiseRestriction> items,
257 std::vector<PairwiseRestriction>* result);
258
259// Same as above, but test `items` against `other_items` and append the
260// restrictions found to `result`.
262 absl::Span<const ItemForPairwiseRestriction> items,
263 absl::Span<const ItemForPairwiseRestriction> other_items,
264 std::vector<PairwiseRestriction>* result);
265
266// This class is used by the no_overlap_2d constraint to maintain the envelope
267// of a set of rectangles. This envelope is not the convex hull, but the exact
268// polyline (aligned with the x and y axis) that contains all the rectangles
269// passed with the AddRectangle() call.
271 public:
272 // Simple start of a rectangle. This is used to represent the residual
273 // capacity profile.
274 struct Rectangle {
275 Rectangle(IntegerValue start, IntegerValue height)
276 : start(start), height(height) {}
277
278 bool operator<(const Rectangle& other) const { return start < other.start; }
279 bool operator==(const Rectangle& other) const {
280 return start == other.start && height == other.height;
281 }
282
283 IntegerValue start = IntegerValue(0);
284 IntegerValue height = IntegerValue(0);
285 };
286
287 void Clear();
288
289 // Adds a rectangle to the current shape.
290 void AddRectangle(IntegerValue x_min, IntegerValue x_max, IntegerValue y_min,
291 IntegerValue y_max);
292
293 // Adds a mandatory profile consumption. All mandatory usages will be
294 // subtracted from the y_max-y_min profile to build the residual capacity.
295 void AddMandatoryConsumption(IntegerValue x_min, IntegerValue x_max,
296 IntegerValue y_height);
297
298 // Returns the profile of the function:
299 // capacity(x) = max(y_max of rectangles overlapping x) - min(y_min of
300 // rectangle overlapping x) - sum(y_height of mandatory rectangles
301 // overlapping x) where a rectangle overlaps x if x_min <= x < x_max.
302 //
303 // Note the profile can contain negative heights in case the mandatory part
304 // exceeds the range on the y axis.
305 //
306 // Note that it adds a sentinel (kMinIntegerValue, 0) at the start. It is
307 // useful when we reverse the direction on the x axis.
308 void BuildResidualCapacityProfile(std::vector<Rectangle>* result);
309
310 // Returns the exact area of the bounding polyline of all rectangles added.
311 //
312 // Note that this will redo the computation each time.
313 IntegerValue GetBoundingArea();
314
315 private:
316 // Type for the capacity events.
317 enum EventType { START_RECTANGLE, END_RECTANGLE, CHANGE_MANDATORY_PROFILE };
318
319 // Individual events.
320 struct Event {
321 IntegerValue time;
322 IntegerValue y_min;
323 IntegerValue y_max;
324 EventType type;
325 int index;
326
327 bool operator<(const Event& other) const { return time < other.time; }
328 };
329
330 // Element of the integer_pq heap.
331 struct QueueElement {
332 int Index() const { return index; }
333 bool operator<(const QueueElement& o) const { return value < o.value; }
334
335 int index;
336 IntegerValue value;
337 };
338
339 static Event StartRectangleEvent(int index, IntegerValue x_min,
340 IntegerValue y_min, IntegerValue y_max) {
341 return {x_min, y_min, y_max, START_RECTANGLE, index};
342 }
343
344 static Event EndRectangleEvent(int index, IntegerValue x_max) {
345 return {x_max, kMinIntegerValue, kMinIntegerValue, END_RECTANGLE, index};
346 }
347
348 static Event ChangeMandatoryProfileEvent(IntegerValue x, IntegerValue delta) {
349 return {x, /*y_min=*/delta, /*y_max=*/kMinIntegerValue,
350 CHANGE_MANDATORY_PROFILE, /*index=*/-1};
351 }
352
353 std::vector<Event> events_;
354 int num_rectangles_added_ = 0;
355};
356
357// 1D counterpart of RectangleInRange::GetMinimumIntersectionArea.
358// Finds the minimum possible overlap of a interval of size `size` that fits in
359// [range_min, range_max] and a second interval [interval_min, interval_max].
360IntegerValue Smallest1DIntersection(IntegerValue range_min,
361 IntegerValue range_max, IntegerValue size,
362 IntegerValue interval_min,
363 IntegerValue interval_max);
364
365// A rectangle of size (`x_size`, `y_size`) that can freely move inside the
366// `bounding_area` rectangle.
369 Rectangle bounding_area;
370 IntegerValue x_size;
371 IntegerValue y_size;
372
373 enum Corner {
374 BOTTOM_LEFT = 0,
375 TOP_LEFT = 1,
376 BOTTOM_RIGHT = 2,
377 TOP_RIGHT = 3,
378 };
379
380 // Returns the position of the rectangle fixed to one of the corner of its
381 // range.
382 Rectangle GetAtCorner(Corner p) const {
383 switch (p) {
384 case Corner::BOTTOM_LEFT:
385 return Rectangle{.x_min = bounding_area.x_min,
386 .x_max = bounding_area.x_min + x_size,
387 .y_min = bounding_area.y_min,
388 .y_max = bounding_area.y_min + y_size};
389 case Corner::TOP_LEFT:
390 return Rectangle{.x_min = bounding_area.x_min,
391 .x_max = bounding_area.x_min + x_size,
392 .y_min = bounding_area.y_max - y_size,
393 .y_max = bounding_area.y_max};
394 case Corner::BOTTOM_RIGHT:
395 return Rectangle{.x_min = bounding_area.x_max - x_size,
396 .x_max = bounding_area.x_max,
397 .y_min = bounding_area.y_min,
398 .y_max = bounding_area.y_min + y_size};
399 case Corner::TOP_RIGHT:
400 return Rectangle{.x_min = bounding_area.x_max - x_size,
401 .x_max = bounding_area.x_max,
402 .y_min = bounding_area.y_max - y_size,
403 .y_max = bounding_area.y_max};
404 }
405 }
406
407 Rectangle GetBoudingBox() const { return bounding_area; }
408
409 // Returns an empty rectangle if it is possible for no intersection to happen.
410 Rectangle GetMinimumIntersection(const Rectangle& containing_area) const {
411 IntegerValue smallest_area = std::numeric_limits<IntegerValue>::max();
412 Rectangle best_intersection;
413 for (int corner_idx = 0; corner_idx < 4; ++corner_idx) {
414 const Corner p = static_cast<Corner>(corner_idx);
415 Rectangle intersection = containing_area.Intersect(GetAtCorner(p));
416 const IntegerValue intersection_area = intersection.Area();
417 if (intersection_area == 0) {
418 return Rectangle::GetEmpty();
419 }
420 if (intersection_area < smallest_area) {
421 smallest_area = intersection_area;
422 best_intersection = std::move(intersection);
423 }
424 }
425 return best_intersection;
426 }
427
429 const Rectangle& containing_area) const {
430 return Smallest1DIntersection(bounding_area.x_min, bounding_area.x_max,
431 x_size, containing_area.x_min,
432 containing_area.x_max) *
433 Smallest1DIntersection(bounding_area.y_min, bounding_area.y_max,
434 y_size, containing_area.y_min,
435 containing_area.y_max);
436 }
437
439 const Rectangle& containing_area, const RectangleInRange& original,
440 const IntegerValue& min_intersect_x,
441 const IntegerValue& min_intersect_y) {
442 const IntegerValue x_size = original.x_size;
443 const IntegerValue y_size = original.y_size;
444
445 RectangleInRange result;
446 result.x_size = x_size;
447 result.y_size = y_size;
448 result.box_index = original.box_index;
449
450 // We cannot intersect more units than the whole item.
451 DCHECK_GE(x_size, min_intersect_x);
452 DCHECK_GE(y_size, min_intersect_y);
453
454 // Units that can *not* intersect per dimension.
455 const IntegerValue x_headroom = x_size - min_intersect_x;
456 const IntegerValue y_headroom = y_size - min_intersect_y;
457
458 result.bounding_area.x_min = containing_area.x_min - x_headroom;
459 result.bounding_area.x_max = containing_area.x_max + x_headroom;
460 result.bounding_area.y_min = containing_area.y_min - y_headroom;
461 result.bounding_area.y_max = containing_area.y_max + y_headroom;
462
463 return result;
464 }
465
466 template <typename Sink>
467 friend void AbslStringify(Sink& sink, const RectangleInRange& r) {
468 absl::Format(&sink, "item(size=%vx%v, BB=%v)", r.x_size, r.y_size,
469 r.bounding_area);
470 }
471};
472
473// Cheaply test several increasingly smaller rectangles for energy conflict.
474// More precisely, each call to `Shrink()` cost O(k + n) operations, where k is
475// the number of points that shrinking the probing rectangle will cross and n is
476// the number of items which are in a range that overlaps the probing rectangle
477// in both sides in the dimension that is getting shrinked. When calling
478// repeatedely `Shrink()` until the probing rectangle collapse into a single
479// point, the O(k) component adds up to a O(M) cost, where M is the number of
480// items. This means this procedure is linear in time if the ranges of the items
481// are small.
482//
483// The energy is defined as the minimum occupied area inside the probing
484// rectangle. For more details, see Clautiaux, François, et al. "A new
485// constraint programming approach for the orthogonal packing problem."
486// Computers & Operations Research 35.3 (2008): 944-959.
487//
488// This is used by FindRectanglesWithEnergyConflictMC() below.
490 public:
491 // It will initialize with the bounding box of the whole set.
492 explicit ProbingRectangle(const std::vector<RectangleInRange>& intervals);
493
494 enum Edge { TOP = 0, LEFT = 1, BOTTOM = 2, RIGHT = 3 };
495
496 // Reset to the bounding box of the whole set.
497 void Reset();
498
499 // Shrink the rectangle by moving one of its four edges to the next
500 // "interesting" value. The interesting values for x or y are the ones that
501 // correspond to a boundary, ie., a value that corresponds to one of {min,
502 // min + size, max - size, max} of a rectangle.
503 void Shrink(Edge edge);
504
505 bool CanShrink(Edge edge) const;
506
507 bool IsMinimal() const {
508 // We only need to know if there is slack on both dimensions. Actually
509 // CanShrink(BOTTOM) == CanShrink(TOP) and conversely.
510 return !(CanShrink(Edge::BOTTOM) || CanShrink(Edge::LEFT));
511 }
512
513 // Test-only method that check that all internal incremental counts are
514 // correct by comparing with recalculating them from scratch.
515 void ValidateInvariants() const;
516
517 // How much of GetMinimumEnergy() will change if Shrink() is called.
518 IntegerValue GetShrinkDeltaEnergy(Edge edge) const {
519 return cached_delta_energy_[edge];
520 }
521
522 // How much of GetCurrentRectangleArea() will change if Shrink() is called.
523 IntegerValue GetShrinkDeltaArea(Edge edge) const;
524
525 Rectangle GetCurrentRectangle() const;
526 IntegerValue GetCurrentRectangleArea() const { return probe_area_; }
527
528 // This is equivalent of, for every item:
529 // - Call GetMinimumIntersectionArea() with GetCurrentRectangle().
530 // - Return the total sum of the areas.
531 IntegerValue GetMinimumEnergy() const { return minimum_energy_; }
532
533 const std::vector<RectangleInRange>& Intervals() const { return intervals_; }
534
536 LEFT_AND_RIGHT = 0,
537 TOP_AND_BOTTOM = 1,
538 };
539
540 private:
541 void CacheShrinkDeltaEnergy(int dimension);
542
543 template <Edge edge>
544 void ShrinkImpl();
545
546 struct IntervalPoint {
547 IntegerValue value;
548 int index;
549 };
550
551 std::vector<IntervalPoint> interval_points_sorted_by_x_;
552 std::vector<IntervalPoint> interval_points_sorted_by_y_;
553
554 // Those two vectors are not strictly needed, we could instead iterate
555 // directly on the two vectors above, but the code would be much uglier.
556 struct PointsForCoordinate {
557 IntegerValue coordinate;
558 absl::Span<IntervalPoint> items_touching_coordinate;
559 };
560 std::vector<PointsForCoordinate> grouped_intervals_sorted_by_x_;
561 std::vector<PointsForCoordinate> grouped_intervals_sorted_by_y_;
562
563 const std::vector<RectangleInRange>& intervals_;
564
565 IntegerValue full_energy_;
566 IntegerValue minimum_energy_;
567 IntegerValue probe_area_;
568 int indexes_[4];
569 int next_indexes_[4];
570
571 absl::flat_hash_set<int> ranges_touching_both_boundaries_[2];
572 IntegerValue corner_count_[4] = {0, 0, 0, 0};
573 IntegerValue intersect_length_[4] = {0, 0, 0, 0};
574 IntegerValue cached_delta_energy_[4];
575};
576
577// Monte-Carlo inspired heuristic to find a rectangles with an energy conflict:
578// - start with a rectangle equals to the full bounding box of the elements;
579// - shrink the rectangle by an edge to the next "interesting" value. Choose
580// the edge randomly, but biased towards the change that increases the ratio
581// area_inside / area_rectangle;
582// - collect a result at every conflict or every time the ratio
583// used_energy/available_energy is more than `candidate_energy_usage_factor`;
584// - stop when the rectangle is empty.
586 // Known conflicts: the minimal energy used inside the rectangle is larger
587 // than the area of the rectangle.
588 std::vector<Rectangle> conflicts;
589 // Rectangles without a conflict but having used_energy/available_energy >
590 // candidate_energy_usage_factor. Those are good candidates for finding
591 // conflicts using more sophisticated heuristics. Those rectangles are
592 // ordered so the n-th rectangle is always fully inside the n-1-th one.
593 std::vector<Rectangle> candidates;
594};
596 const std::vector<RectangleInRange>& intervals, absl::BitGenRef random,
597 double temperature, double candidate_energy_usage_factor);
598
599// Render a packing solution as a Graphviz dot file. Only works in the "neato"
600// or "fdp" Graphviz backends.
601std::string RenderDot(std::optional<Rectangle> bb,
602 absl::Span<const Rectangle> solution);
603
604// Given a bounding box and a list of rectangles inside that bounding box,
605// returns a list of rectangles partitioning the empty area inside the bounding
606// box.
607std::vector<Rectangle> FindEmptySpaces(
608 const Rectangle& bounding_box, std::vector<Rectangle> ocupied_rectangles);
609
610} // namespace sat
611} // namespace operations_research
612
613#endif // OR_TOOLS_SAT_DIFFN_UTIL_H_
IntegerValue y
IntegerValue size
IntegerValue GetShrinkDeltaEnergy(Edge edge) const
How much of GetMinimumEnergy() will change if Shrink() is called.
Definition diffn_util.h:518
const std::vector< RectangleInRange > & Intervals() const
Definition diffn_util.h:533
int64_t b
Definition table.cc:45
int64_t a
Definition table.cc:44
int64_t height
int64_t value
Edge edge
int index
double solution
void AppendPairwiseRestrictions(absl::Span< const ItemForPairwiseRestriction > items, std::vector< PairwiseRestriction > *result)
bool BoxesAreInEnergyConflict(const std::vector< Rectangle > &rectangles, const std::vector< IntegerValue > &energies, absl::Span< const int > boxes, Rectangle *conflict)
absl::Span< int > FilterBoxesAndRandomize(absl::Span< const Rectangle > cached_rectangles, absl::Span< int > boxes, IntegerValue threshold_x, IntegerValue threshold_y, absl::BitGenRef random)
bool AnalyzeIntervals(bool transpose, absl::Span< const int > local_boxes, absl::Span< const Rectangle > rectangles, absl::Span< const IntegerValue > rectangle_energies, IntegerValue *x_threshold, IntegerValue *y_threshold, Rectangle *conflict)
void ConstructOverlappingSets(bool already_sorted, std::vector< IndexedInterval > *intervals, std::vector< std::vector< int > > *result)
constexpr IntegerValue kMinIntegerValue(-kMaxIntegerValue.value())
std::vector< Rectangle > FindEmptySpaces(const Rectangle &bounding_box, std::vector< Rectangle > ocupied_rectangles)
absl::Span< int > FilterBoxesThatAreTooLarge(absl::Span< const Rectangle > cached_rectangles, absl::Span< const IntegerValue > energies, absl::Span< int > boxes)
std::vector< int > GetIntervalArticulationPoints(std::vector< IndexedInterval > *intervals)
std::ostream & operator<<(std::ostream &os, const BoolVar &var)
Definition cp_model.cc:89
std::string RenderDot(std::optional< Rectangle > bb, absl::Span< const Rectangle > solution)
bool ReportEnergyConflict(Rectangle bounding_box, absl::Span< const int > boxes, SchedulingConstraintHelper *x, SchedulingConstraintHelper *y)
std::vector< absl::Span< int > > GetOverlappingRectangleComponents(absl::Span< const Rectangle > rectangles, absl::Span< int > active_rectangles)
FindRectanglesResult FindRectanglesWithEnergyConflictMC(const std::vector< RectangleInRange > &intervals, absl::BitGenRef random, double temperature, double candidate_energy_usage_factor)
IntegerValue Smallest1DIntersection(IntegerValue range_min, IntegerValue range_max, IntegerValue size, IntegerValue interval_min, IntegerValue interval_max)
void GetOverlappingIntervalComponents(std::vector< IndexedInterval > *intervals, std::vector< std::vector< int > > *components)
In SWIG mode, we don't want anything besides these top-level includes.
const Variable x
Definition qp_tests.cc:127
int64_t time
Definition resource.cc:1708
int64_t delta
Definition resource.cc:1709
IntervalVar * interval
Definition resource.cc:101
std::optional< int64_t > end
int64_t start
bool operator==(const Rectangle &other) const
Definition diffn_util.h:279
bool operator<(const Rectangle &other) const
Definition diffn_util.h:278
Rectangle(IntegerValue start, IntegerValue height)
Definition diffn_util.h:275
bool operator()(const IndexedInterval &a, const IndexedInterval &b) const
Definition diffn_util.h:183
bool operator()(const IndexedInterval &a, const IndexedInterval &b) const
Definition diffn_util.h:189
bool operator==(const IndexedInterval &rhs) const
Definition diffn_util.h:175
bool operator==(const PairwiseRestriction &rhs) const
Definition diffn_util.h:247
Rectangle GetMinimumIntersection(const Rectangle &containing_area) const
Returns an empty rectangle if it is possible for no intersection to happen.
Definition diffn_util.h:410
IntegerValue GetMinimumIntersectionArea(const Rectangle &containing_area) const
Definition diffn_util.h:428
friend void AbslStringify(Sink &sink, const RectangleInRange &r)
Definition diffn_util.h:467
static RectangleInRange BiggestWithMinIntersection(const Rectangle &containing_area, const RectangleInRange &original, const IntegerValue &min_intersect_x, const IntegerValue &min_intersect_y)
Definition diffn_util.h:438
Rectangle GetAtCorner(Corner p) const
Definition diffn_util.h:382
bool operator==(const Rectangle &other) const
Definition diffn_util.h:74
void GrowToInclude(const Rectangle &other)
Definition diffn_util.h:46
friend void AbslStringify(Sink &sink, const Rectangle &r)
Definition diffn_util.h:69