From 52a91707f67429c8eefc5718e369e491bd3b7863 Mon Sep 17 00:00:00 2001 From: Laurent Perron Date: Wed, 22 Jan 2025 14:35:31 +0100 Subject: [PATCH] fix inconsistent behavior of Domain factories with invalid intervals --- ortools/util/sorted_interval_list.cc | 16 +++++++++++++--- ortools/util/sorted_interval_list.h | 17 ++++++++++++++++- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/ortools/util/sorted_interval_list.cc b/ortools/util/sorted_interval_list.cc index 3f0d8372d1..71296c828c 100644 --- a/ortools/util/sorted_interval_list.cc +++ b/ortools/util/sorted_interval_list.cc @@ -64,6 +64,16 @@ std::string IntervalsAsString(const Intervals& intervals) { return result; } +void SortAndRemoveInvalidIntervals( + absl::InlinedVector* intervals) { + intervals->erase(std::remove_if(intervals->begin(), intervals->end(), + [](const ClosedInterval& interval) { + return interval.start > interval.end; + }), + intervals->end()); + std::sort(intervals->begin(), intervals->end()); +} + // Transforms a sorted list of intervals in a sorted DISJOINT list for which // IntervalsAreSortedAndNonAdjacent() would return true. void UnionOfSortedIntervals(absl::InlinedVector* intervals) { @@ -163,7 +173,7 @@ Domain Domain::FromValues(std::vector values) { Domain Domain::FromIntervals(absl::Span intervals) { Domain result; result.intervals_.assign(intervals.begin(), intervals.end()); - std::sort(result.intervals_.begin(), result.intervals_.end()); + SortAndRemoveInvalidIntervals(&result.intervals_); UnionOfSortedIntervals(&result.intervals_); return result; } @@ -176,7 +186,7 @@ Domain Domain::FromFlatSpanOfIntervals( for (int i = 0; i < flat_intervals.size(); i += 2) { result.intervals_.push_back({flat_intervals[i], flat_intervals[i + 1]}); } - std::sort(result.intervals_.begin(), result.intervals_.end()); + SortAndRemoveInvalidIntervals(&result.intervals_); UnionOfSortedIntervals(&result.intervals_); return result; } @@ -196,7 +206,7 @@ Domain Domain::FromVectorIntervals( result.intervals_.push_back({interval[0], interval[1]}); } } - std::sort(result.intervals_.begin(), result.intervals_.end()); + SortAndRemoveInvalidIntervals(&result.intervals_); UnionOfSortedIntervals(&result.intervals_); return result; } diff --git a/ortools/util/sorted_interval_list.h b/ortools/util/sorted_interval_list.h index 15a1aa2903..07a55b7616 100644 --- a/ortools/util/sorted_interval_list.h +++ b/ortools/util/sorted_interval_list.h @@ -131,12 +131,18 @@ class Domain { /** * Creates a domain from the union of an unsorted list of intervals. + * + * Note that invalid intervals (start > end) will log a DFATAL error and will + * be ignored. */ static Domain FromIntervals(absl::Span intervals); /** * Same as FromIntervals() for a flattened representation (start, end, * start, end, ...). + * + * Note that invalid intervals (start > end) will log a DFATAL error and will + * be ignored. */ static Domain FromFlatSpanOfIntervals( absl::Span flat_intervals); @@ -144,7 +150,13 @@ class Domain { /** * This method is available in Python, Java and .NET. It allows * building a Domain object from a list of intervals (long[][] in Java and - * .NET, [[0, 2], [5, 5], [8, 10]] in python). + * .NET, [[0, 2], [5], [8, 10]] in python). + * + * Note that the intervals can be defined with a single value (i.e. [5]), or + * two increasing values (i.e. [8, 10]). + * + * Invalid intervals (start > end) will log a DFATAL error and will be + * ignored. */ static Domain FromVectorIntervals( const std::vector >& intervals); @@ -153,6 +165,9 @@ class Domain { * This method is available in Python, Java and .NET. It allows * building a Domain object from a flattened list of intervals * (long[] in Java and .NET, [0, 2, 5, 5, 8, 10] in python). + * + * Note that invalid intervals (start > end) will log a DFATAL error and will + * be ignored. */ static Domain FromFlatIntervals(const std::vector& flat_intervals);