14#ifndef ORTOOLS_SAT_DIFFN_UTIL_H_
15#define ORTOOLS_SAT_DIFFN_UTIL_H_
28#include "absl/container/flat_hash_set.h"
29#include "absl/container/inlined_vector.h"
30#include "absl/log/check.h"
31#include "absl/log/log.h"
32#include "absl/random/bit_gen_ref.h"
33#include "absl/strings/str_format.h"
34#include "absl/types/span.h"
83 template <
typename Sink>
85 absl::Format(&sink,
"rectangle(x(%i..%i), y(%i..%i))", r.
x_min.value(),
97 return Rectangle{.x_min = IntegerValue(0),
98 .x_max = IntegerValue(0),
99 .y_min = IntegerValue(0),
100 .y_max = IntegerValue(0)};
105 const IntegerValue ret_x_min = std::max(
x_min, other.
x_min);
106 const IntegerValue ret_y_min = std::max(
y_min, other.
y_min);
107 const IntegerValue ret_x_max = std::min(
x_max, other.
x_max);
108 const IntegerValue ret_y_max = std::min(
y_max, other.
y_max);
110 if (ret_x_min >= ret_x_max || ret_y_min >= ret_y_max) {
121 const IntegerValue ret_x_min = std::max(
x_min, other.
x_min);
122 const IntegerValue ret_y_min = std::max(
y_min, other.
y_min);
123 const IntegerValue ret_x_max = std::min(
x_max, other.
x_max);
124 const IntegerValue ret_y_max = std::min(
y_max, other.
y_max);
126 if (ret_x_min >= ret_x_max || ret_y_min >= ret_y_max) {
129 return (ret_x_max - ret_x_min) * (ret_y_max - ret_y_min);
135 const double diff_x =
136 (
static_cast<double>(a.
x_min.value()) + a.
x_max.value()) / 2.0 -
137 (
static_cast<double>(
b.x_min.value()) +
b.x_max.value()) / 2.0;
138 const double diff_y =
139 (
static_cast<double>(a.
y_min.value()) + a.
y_max.value()) / 2.0 -
140 (
static_cast<double>(
b.y_min.value()) +
b.y_max.value()) / 2.0;
141 return std::sqrt(diff_x * diff_x + diff_y * diff_y);
146 const double diff_x =
147 (
static_cast<double>(a.
x_min.value()) + a.
x_max.value()) / 2.0 -
148 (
static_cast<double>(
b.x_min.value()) +
b.x_max.value()) / 2.0;
149 const double diff_y =
150 (
static_cast<double>(a.
y_min.value()) + a.
y_max.value()) / 2.0 -
151 (
static_cast<double>(
b.y_min.value()) +
b.y_max.value()) / 2.0;
152 return std::max(std::abs(diff_x), std::abs(diff_y));
158 absl::Span<const Rectangle> rectangles);
163 absl::Span<const IntegerValue> energies,
164 absl::Span<const int> boxes,
165 Rectangle* conflict =
nullptr);
174 SchedulingConstraintHelper* x,
175 SchedulingConstraintHelper* y);
186 absl::Span<const Rectangle> rectangles,
187 absl::Span<const IntegerValue> rectangle_energies,
188 IntegerValue* x_threshold, IntegerValue* y_threshold,
189 Rectangle* conflict =
nullptr);
195 absl::Span<const Rectangle> cached_rectangles, absl::Span<int> boxes,
196 IntegerValue threshold_x, IntegerValue threshold_y, absl::BitGenRef random);
203 absl::Span<const Rectangle> cached_rectangles,
204 absl::Span<const IntegerValue> energies, absl::Span<int> boxes);
221 std::tie(
b.start,
b.end,
b.index);
230 template <
typename Sink>
232 absl::Format(&sink,
"[%v..%v] (#%v)", interval.
start, interval.
end,
252 CompactVectorVector<int>* result,
253 absl::Span<const int> order = {});
260 std::vector<IndexedInterval>* intervals,
261 std::vector<std::vector<int>>* components);
268 std::vector<IndexedInterval>* intervals);
282 bool IsFixed()
const {
return x.IsFixed() &&
y.IsFixed(); }
284 template <
typename Sink>
286 absl::Format(&sink,
"Item %v: [(%v..%v)-(%v..%v)] x [(%v..%v)-(%v..%v)]",
319 std::vector<PairwiseRestriction>* result);
324 absl::Span<const ItemWithVariableSize> items,
325 absl::Span<const ItemWithVariableSize> other_items,
326 std::vector<PairwiseRestriction>* result);
345 IntegerValue
start = IntegerValue(0);
352 void AddRectangle(IntegerValue x_min, IntegerValue x_max, IntegerValue y_min,
358 IntegerValue y_height);
379 enum EventType { START_RECTANGLE, END_RECTANGLE, CHANGE_MANDATORY_PROFILE };
389 bool operator<(
const Event& other)
const {
return time < other.time; }
393 struct QueueElement {
394 int Index()
const {
return index; }
395 bool operator<(
const QueueElement& o)
const {
return value < o.value; }
401 static Event StartRectangleEvent(
int index, IntegerValue x_min,
402 IntegerValue y_min, IntegerValue y_max) {
403 return {x_min, y_min, y_max, START_RECTANGLE, index};
406 static Event EndRectangleEvent(
int index, IntegerValue x_max) {
410 static Event ChangeMandatoryProfileEvent(IntegerValue x, IntegerValue delta) {
412 CHANGE_MANDATORY_PROFILE, -1};
415 std::vector<Event> events_;
416 int num_rectangles_added_ = 0;
423 IntegerValue range_max, IntegerValue size,
424 IntegerValue interval_min,
425 IntegerValue interval_max);
473 LOG(FATAL) <<
"Invalid corner: " <<
static_cast<int>(p);
480 IntegerValue smallest_area = std::numeric_limits<IntegerValue>::max();
482 for (
int corner_idx = 0; corner_idx < 4; ++corner_idx) {
485 const IntegerValue intersection_area = intersection.
Area();
486 if (intersection_area == 0) {
489 if (intersection_area < smallest_area) {
490 smallest_area = intersection_area;
491 best_intersection = std::move(intersection);
494 return best_intersection;
498 const Rectangle& containing_area)
const {
501 containing_area.
x_max) *
504 containing_area.
y_max);
521 const IntegerValue& min_intersect_x,
522 const IntegerValue& min_intersect_y) {
532 DCHECK_GE(
x_size, min_intersect_x);
533 DCHECK_GE(
y_size, min_intersect_y);
536 const IntegerValue x_headroom =
x_size - min_intersect_x;
537 const IntegerValue y_headroom =
y_size - min_intersect_y;
547 template <
typename Sink>
549 absl::Format(&sink,
"item(size=%vx%v, BB=%v)", r.
x_size, r.
y_size,
600 return cached_delta_energy_[edge];
614 const std::vector<RectangleInRange>&
Intervals()
const {
return intervals_; }
622 void CacheShrinkDeltaEnergy(
int dimension);
627 struct IntervalPoint {
632 std::vector<IntervalPoint> interval_points_sorted_by_x_;
633 std::vector<IntervalPoint> interval_points_sorted_by_y_;
637 struct PointsForCoordinate {
638 IntegerValue coordinate;
639 absl::Span<IntervalPoint> items_touching_coordinate;
641 std::vector<PointsForCoordinate> grouped_intervals_sorted_by_x_;
642 std::vector<PointsForCoordinate> grouped_intervals_sorted_by_y_;
644 const std::vector<RectangleInRange>& intervals_;
646 IntegerValue full_energy_;
647 IntegerValue minimum_energy_;
648 IntegerValue probe_area_;
650 int next_indexes_[4];
652 absl::flat_hash_set<int> ranges_touching_both_boundaries_[2];
653 IntegerValue corner_count_[4] = {0, 0, 0, 0};
654 IntegerValue intersect_length_[4] = {0, 0, 0, 0};
655 IntegerValue cached_delta_energy_[4];
677 const std::vector<RectangleInRange>& intervals, absl::BitGenRef random,
678 double temperature,
double candidate_energy_usage_factor);
682std::string
RenderDot(std::optional<Rectangle> bb,
683 absl::Span<const Rectangle>
solution,
684 std::string_view extra_dot_payload =
"");
690 const Rectangle& bounding_box, std::vector<Rectangle> ocupied_rectangles);
697 std::vector<Rectangle> original_region,
698 absl::Span<const Rectangle> area_to_remove);
702 absl::Span<const Rectangle> other) {
725 absl::Span<const Rectangle> rectangles);
736 absl::Span<const Rectangle> rectangles);
741 absl::Span<const Rectangle> rectangles);
void AddMandatoryConsumption(IntegerValue x_min, IntegerValue x_max, IntegerValue y_height)
void AddRectangle(IntegerValue x_min, IntegerValue x_max, IntegerValue y_min, IntegerValue y_max)
IntegerValue GetBoundingArea()
void BuildResidualCapacityProfile(std::vector< Rectangle > *result)
IntegerValue GetShrinkDeltaEnergy(Edge edge) const
IntegerValue GetCurrentRectangleArea() const
IntegerValue GetMinimumEnergy() const
IntegerValue GetShrinkDeltaArea(Edge edge) const
const std::vector< RectangleInRange > & Intervals() const
void ValidateInvariants() const
ProbingRectangle(const std::vector< RectangleInRange > &intervals)
Rectangle GetCurrentRectangle() const
bool CanShrink(Edge edge) const
bool RegionIncludesOther(absl::Span< const Rectangle > region, absl::Span< const Rectangle > other)
CompactVectorVector< int > GetOverlappingRectangleComponents(absl::Span< const Rectangle > rectangles)
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)
std::optional< std::pair< int, int > > FindOneIntersectionIfPresent(absl::Span< const Rectangle > rectangles)
double CenterToCenterLInfinityDistance(const Rectangle &a, const Rectangle &b)
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)
double CenterToCenterL2Distance(const Rectangle &a, const Rectangle &b)
void AppendPairwiseRestrictions(absl::Span< const ItemWithVariableSize > items, std::vector< PairwiseRestriction > *result)
void ConstructOverlappingSets(absl::Span< IndexedInterval > intervals, CompactVectorVector< int > *result, absl::Span< const int > order)
bool ReportEnergyConflict(Rectangle bounding_box, absl::Span< const int > boxes, SchedulingConstraintHelper *x, SchedulingConstraintHelper *y)
FindRectanglesResult FindRectanglesWithEnergyConflictMC(const std::vector< RectangleInRange > &intervals, absl::BitGenRef random, double temperature, double candidate_energy_usage_factor)
std::vector< Rectangle > PavedRegionDifference(std::vector< Rectangle > original_region, absl::Span< const Rectangle > area_to_remove)
bool BoxesAreInEnergyConflict(absl::Span< const Rectangle > rectangles, absl::Span< const IntegerValue > energies, absl::Span< const int > boxes, Rectangle *conflict)
std::optional< std::pair< int, int > > FindOneIntersectionIfPresentWithZeroArea(absl::Span< const Rectangle > rectangles)
std::vector< std::pair< int, int > > FindPartialRectangleIntersections(absl::Span< const Rectangle > rectangles)
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)
IntegerValue CapSubI(IntegerValue a, IntegerValue b)
IntegerValue CapProdI(IntegerValue a, IntegerValue b)
std::string RenderDot(std::optional< Rectangle > bb, absl::Span< const Rectangle > solution, std::string_view extra_dot_payload)
Select next search node to expand Select next item_i to add this new search node to the search Generate a new search node where item_i is not in the knapsack Check validity of this new partial solution(using propagators) - If valid
bool operator==(const Rectangle &other) const
bool operator<(const Rectangle &other) const
Rectangle(IntegerValue start, IntegerValue height)
std::vector< Rectangle > conflicts
std::vector< Rectangle > candidates
bool operator()(const IndexedInterval &a, const IndexedInterval &b) const
bool operator()(const IndexedInterval &a, const IndexedInterval &b) const
bool operator==(const IndexedInterval &rhs) const
friend void AbslStringify(Sink &sink, const IndexedInterval &interval)
friend void AbslStringify(Sink &sink, const ItemWithVariableSize &item)
PairwiseRestrictionType type
bool operator==(const PairwiseRestriction &rhs) const
Rectangle GetMandatoryRegion() const
Rectangle GetMinimumIntersection(const Rectangle &containing_area) const
Rectangle GetBoudingBox() const
IntegerValue GetMinimumIntersectionArea(const Rectangle &containing_area) const
friend void AbslStringify(Sink &sink, const RectangleInRange &r)
static RectangleInRange BiggestWithMinIntersection(const Rectangle &containing_area, const RectangleInRange &original, const IntegerValue &min_intersect_x, const IntegerValue &min_intersect_y)
bool operator==(const RectangleInRange &other) const
Rectangle GetAtCorner(Corner p) const
static Rectangle GetEmpty()
bool operator==(const Rectangle &other) const
void GrowToInclude(const Rectangle &other)
bool operator!=(const Rectangle &other) const
IntegerValue CapArea() const
absl::InlinedVector< Rectangle, 4 > RegionDifference(const Rectangle &other) const
IntegerValue Area() const
IntegerValue SizeY() const
bool IsInsideOf(const Rectangle &other) const
IntegerValue SizeX() const
bool IsDisjoint(const Rectangle &other) const
Rectangle Intersect(const Rectangle &other) const
IntegerValue IntersectArea(const Rectangle &other) const
friend void AbslStringify(Sink &sink, const Rectangle &r)