Google OR-Tools v9.11
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
sorted_interval_list.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_UTIL_SORTED_INTERVAL_LIST_H_
15#define OR_TOOLS_UTIL_SORTED_INTERVAL_LIST_H_
16
17#include <cstdint>
18#include <iterator>
19#include <ostream>
20#include <set>
21#include <string>
22#include <utility>
23#include <vector>
24
25#include "absl/container/inlined_vector.h"
26#include "absl/types/span.h"
28
29namespace operations_research {
30
36 ClosedInterval(int64_t s, int64_t e) : start(s), end(e) {
37 DLOG_IF(DFATAL, s > e) << "Invalid ClosedInterval(" << s << ", " << e
38 << ")";
39 }
40
41 std::string DebugString() const;
42 bool operator==(const ClosedInterval& other) const {
43 return start == other.start && end == other.end;
44 }
45
46 // Because we mainly manipulate vector of disjoint intervals, we only need to
47 // sort by the start. We do not care about the order in which interval with
48 // the same start appear since they will always be merged into one interval.
49 bool operator<(const ClosedInterval& other) const {
50 return start < other.start;
51 }
52
53 template <typename H>
54 friend H AbslHashValue(H h, const ClosedInterval& interval) {
55 return H::combine(std::move(h), interval.start, interval.end);
56 }
57
58 int64_t start = 0; // Inclusive.
59 int64_t end = 0; // Inclusive.
60};
61
62std::ostream& operator<<(std::ostream& out, const ClosedInterval& interval);
63std::ostream& operator<<(std::ostream& out,
64 const std::vector<ClosedInterval>& intervals);
65
75 absl::Span<const ClosedInterval> intervals);
76
87class Domain {
88 public:
90 Domain() {}
91
92#if !defined(SWIG)
94 Domain(const Domain& other) : intervals_(other.intervals_) {}
95
97 Domain& operator=(const Domain& other) {
98 intervals_ = other.intervals_;
99 return *this;
100 }
101
103 Domain(Domain&& other) noexcept : intervals_(std::move(other.intervals_)) {}
104
106 Domain& operator=(Domain&& other) noexcept {
107 intervals_ = std::move(other.intervals_);
108 return *this;
109 }
110#endif // !defined(SWIG)
111
113 explicit Domain(int64_t value);
114
119 Domain(int64_t left, int64_t right);
120
124 static Domain AllValues();
125
130 static Domain FromValues(std::vector<int64_t> values);
131
135 static Domain FromIntervals(absl::Span<const ClosedInterval> intervals);
136
142 absl::Span<const int64_t> flat_intervals);
143
150 const std::vector<std::vector<int64_t> >& intervals);
151
157 static Domain FromFlatIntervals(const std::vector<int64_t>& flat_intervals);
158
166 std::vector<int64_t> FlattenedIntervals() const;
167
168#if !defined(SWIG)
177 public:
179 const absl::InlinedVector<ClosedInterval, 1>& intervals)
180 : value_(intervals.empty() ? int64_t{0} : intervals.front().start),
181 it_(intervals.begin()),
182 end_(intervals.end()) {}
183
184 int64_t operator*() const { return value_; }
185
186 void operator++() {
187 if (value_ == it_->end) {
188 ++it_;
189 if (it_ != end_) value_ = it_->start;
190 } else {
191 ++value_;
192 }
193 }
194
196 absl::InlinedVector<ClosedInterval, 1>::const_iterator end) const {
197 return it_ != end;
198 }
199
200 private:
201 int64_t value_;
202 absl::InlinedVector<ClosedInterval, 1>::const_iterator it_;
203 absl::InlinedVector<ClosedInterval, 1>::const_iterator end_;
204 };
207 absl::InlinedVector<ClosedInterval, 1>::const_iterator end() const {
208 return intervals.end();
209 }
210 const absl::InlinedVector<ClosedInterval, 1>& intervals;
211 };
214 absl::InlinedVector<ClosedInterval, 1>::const_iterator end() const {
215 return intervals.end();
216 }
217 absl::InlinedVector<ClosedInterval, 1> intervals;
218 };
219 DomainIteratorBeginEnd Values() const& { return {this->intervals_}; }
221 return {std::move(this->intervals_)};
222 }
223#endif // !defined(SWIG)
224
228 bool IsEmpty() const;
229
233 int64_t Size() const;
234
239 bool HasTwoValues() const {
240 if (intervals_.size() == 1) {
241 return intervals_[0].end == intervals_[0].start + 1;
242 } else if (intervals_.size() == 2) {
243 return intervals_[0].end == intervals_[0].start &&
244 intervals_[1].end == intervals_[1].start;
245 }
246 return false;
247 }
248
253 int64_t Min() const;
254
259 int64_t Max() const;
260
264 int64_t SmallestValue() const;
265
270 int64_t ClosestValue(int64_t wanted) const;
271
276 int64_t ValueAtOrBefore(int64_t input) const;
277 int64_t ValueAtOrAfter(int64_t input) const;
278
283 Domain PartAroundZero() const;
284
289 bool IsFixed() const;
290
296 int64_t FixedValue() const;
297
301 bool Contains(int64_t value) const;
302
306 int64_t Distance(int64_t value) const;
307
311 bool IsIncludedIn(const Domain& domain) const;
312
316 Domain Complement() const;
317
324 Domain Negation() const;
325
329 Domain IntersectionWith(const Domain& domain) const;
330
334 Domain UnionWith(const Domain& domain) const;
335
339 Domain AdditionWith(const Domain& domain) const;
340
352 Domain MultiplicationBy(int64_t coeff, bool* exact = nullptr) const;
353
358
371 Domain ContinuousMultiplicationBy(int64_t coeff) const;
372
385 Domain ContinuousMultiplicationBy(const Domain& domain) const;
386
392 Domain DivisionBy(int64_t coeff) const;
393
399 Domain InverseMultiplicationBy(int64_t coeff) const;
400
409 Domain PositiveModuloBySuperset(const Domain& modulo) const;
410
417 Domain PositiveDivisionBySuperset(const Domain& divisor) const;
418
422 Domain SquareSuperset() const;
423
444 Domain SimplifyUsingImpliedDomain(const Domain& implied_domain) const;
445
449 std::string ToString() const;
450
454 bool operator<(const Domain& other) const;
455
456 bool operator==(const Domain& other) const {
457 return intervals_ == other.intervals_;
458 }
459
460 bool operator!=(const Domain& other) const {
461 return intervals_ != other.intervals_;
462 }
463
464 template <typename H>
465 friend H AbslHashValue(H h, const Domain& domain) {
466 return H::combine(std::move(h), domain.intervals_);
467 }
468
474 int NumIntervals() const { return intervals_.size(); }
475 ClosedInterval front() const { return intervals_.front(); }
476 ClosedInterval back() const { return intervals_.back(); }
477 ClosedInterval operator[](int i) const { return intervals_[i]; }
478 absl::InlinedVector<ClosedInterval, 1>::const_iterator begin() const {
479 return intervals_.begin();
480 }
481 absl::InlinedVector<ClosedInterval, 1>::const_iterator end() const {
482 return intervals_.end();
483 }
484
485 private:
486 // Same as Negation() but modify the current domain.
487 void NegateInPlace();
488
489 // Some functions relax the domain when its "complexity" (i.e NumIntervals())
490 // become too large.
491 static constexpr int kDomainComplexityLimit = 100;
492
493 // Invariant: will always satisfy IntervalsAreSortedAndNonAdjacent().
494 //
495 // Note that we use InlinedVector for the common case of single internal
496 // interval. This provide a good performance boost when working with a
497 // std::vector<Domain>.
498 absl::InlinedVector<ClosedInterval, 1> intervals_;
499};
500
501std::ostream& operator<<(std::ostream& out, const Domain& domain);
502
503// Returns the sum of smallest k values in the domain.
504int64_t SumOfKMinValueInDomain(const Domain& domain, int k);
505
506// Returns the sum of largest k values in the domain.
507int64_t SumOfKMaxValueInDomain(const Domain& domain, int k);
508
516// TODO(user): Templatize the class on the type of the bounds.
518 public:
520 bool operator()(const ClosedInterval& a, const ClosedInterval& b) const {
521 return a.start != b.start ? a.start < b.start : a.end < b.end;
522 }
523 };
524 typedef std::set<ClosedInterval, IntervalComparator> IntervalSet;
525 typedef IntervalSet::iterator Iterator;
526 typedef IntervalSet::const_iterator ConstIterator;
527
530 const std::vector<ClosedInterval>& intervals);
531
537 // TODO(user): Explain why we favored this API to the more natural
538 // input std::vector<ClosedInterval> or std::vector<std::pair<int, int>>.
539 SortedDisjointIntervalList(const std::vector<int64_t>& starts,
540 const std::vector<int64_t>& ends);
541 SortedDisjointIntervalList(const std::vector<int>& starts,
542 const std::vector<int>& ends);
543
548 int64_t end);
549
559 Iterator InsertInterval(int64_t start, int64_t end);
560
570 Iterator GrowRightByOne(int64_t value, int64_t* newly_covered);
571
578 void InsertIntervals(const std::vector<int64_t>& starts,
579 const std::vector<int64_t>& ends);
580 void InsertIntervals(const std::vector<int>& starts,
581 const std::vector<int>& ends);
582
586 int NumIntervals() const { return intervals_.size(); }
587
598
599 std::string DebugString() const;
600
611 ConstIterator begin() const { return intervals_.begin(); }
612 ConstIterator end() const { return intervals_.end(); }
613
617 const ClosedInterval& last() const { return *intervals_.rbegin(); }
618
619 void clear() { intervals_.clear(); }
621 intervals_.swap(other.intervals_);
622 }
623
624 private:
625 template <class T>
626 void InsertAll(const std::vector<T>& starts, const std::vector<T>& ends);
627
628 IntervalSet intervals_;
629};
630
631} // namespace operations_research
632
633#endif // OR_TOOLS_UTIL_SORTED_INTERVAL_LIST_H_
DomainIterator(const absl::InlinedVector< ClosedInterval, 1 > &intervals)
bool operator!=(absl::InlinedVector< ClosedInterval, 1 >::const_iterator end) const
Domain SimplifyUsingImpliedDomain(const Domain &implied_domain) const
static Domain FromVectorIntervals(const std::vector< std::vector< int64_t > > &intervals)
DomainIteratorBeginEndWithOwnership Values() const &&
Domain(Domain &&other) noexcept
Move constructor.
Domain MultiplicationBy(int64_t coeff, bool *exact=nullptr) const
static Domain FromValues(std::vector< int64_t > values)
bool operator<(const Domain &other) const
friend H AbslHashValue(H h, const Domain &domain)
int64_t ValueAtOrAfter(int64_t input) const
Domain(const Domain &other)
Copy constructor (mandatory as we define the move constructor).
std::vector< int64_t > FlattenedIntervals() const
Domain IntersectionWith(const Domain &domain) const
static Domain FromIntervals(absl::Span< const ClosedInterval > intervals)
Domain ContinuousMultiplicationBy(int64_t coeff) const
bool Contains(int64_t value) const
DomainIteratorBeginEnd Values() const &
Domain PositiveModuloBySuperset(const Domain &modulo) const
Domain AdditionWith(const Domain &domain) const
bool IsIncludedIn(const Domain &domain) const
static Domain FromFlatIntervals(const std::vector< int64_t > &flat_intervals)
Domain()
By default, Domain will be empty.
Domain DivisionBy(int64_t coeff) const
int64_t Distance(int64_t value) const
Domain & operator=(const Domain &other)
Copy operator (mandatory as we define the move operator).
static Domain FromFlatSpanOfIntervals(absl::Span< const int64_t > flat_intervals)
absl::InlinedVector< ClosedInterval, 1 >::const_iterator end() const
Domain PositiveDivisionBySuperset(const Domain &divisor) const
absl::InlinedVector< ClosedInterval, 1 >::const_iterator begin() const
Domain UnionWith(const Domain &domain) const
bool operator==(const Domain &other) const
Domain & operator=(Domain &&other) noexcept
Move operator.
ClosedInterval operator[](int i) const
Domain InverseMultiplicationBy(int64_t coeff) const
int64_t ValueAtOrBefore(int64_t input) const
bool operator!=(const Domain &other) const
int64_t ClosestValue(int64_t wanted) const
void InsertIntervals(const std::vector< int64_t > &starts, const std::vector< int64_t > &ends)
Iterator InsertInterval(int64_t start, int64_t end)
SortedDisjointIntervalList BuildComplementOnInterval(int64_t start, int64_t end)
void swap(SortedDisjointIntervalList &other)
std::set< ClosedInterval, IntervalComparator > IntervalSet
Iterator GrowRightByOne(int64_t value, int64_t *newly_covered)
int64_t b
Definition table.cc:45
int64_t a
Definition table.cc:44
int64_t value
In SWIG mode, we don't want anything besides these top-level includes.
int64_t SumOfKMinValueInDomain(const Domain &domain, int k)
Returns the sum of smallest k values in the domain.
std::ostream & operator<<(std::ostream &out, const Assignment &assignment)
bool IntervalsAreSortedAndNonAdjacent(absl::Span< const ClosedInterval > intervals)
int64_t SumOfKMaxValueInDomain(const Domain &domain, int k)
Returns the sum of largest k values in the domain.
static int input(yyscan_t yyscanner)
IntervalVar * interval
Definition resource.cc:101
int64_t start
bool operator==(const ClosedInterval &other) const
friend H AbslHashValue(H h, const ClosedInterval &interval)
bool operator<(const ClosedInterval &other) const
absl::InlinedVector< ClosedInterval, 1 >::const_iterator end() const
absl::InlinedVector< ClosedInterval, 1 >::const_iterator end() const
const absl::InlinedVector< ClosedInterval, 1 > & intervals
bool operator()(const ClosedInterval &a, const ClosedInterval &b) const