Clingo
Loading...
Searching...
No Matches
interval_set.hh
1#pragma once
2
3#include <algorithm>
4#include <clingo/util/small_vector.hh>
5
6namespace CppClingo::Util {
7
10
18template <class T> class interval_set {
19 public:
21 using value_type = T;
22 struct right_bound;
23
25 struct left_bound {
27 constexpr left_bound(value_type bound, bool inclusive) : bound{std::move(bound)}, inclusive{inclusive} {}
29 explicit left_bound(right_bound const &x) : bound(x.bound), inclusive(!x.inclusive) {}
30
35 };
36
38 struct right_bound {
40 constexpr right_bound(value_type bound, bool inclusive) : bound{std::move(bound)}, inclusive{inclusive} {}
42 explicit right_bound(left_bound const &x) : bound(x.bound), inclusive(!x.inclusive) {}
43
48 };
49
51 struct interval {
53 constexpr interval(left_bound left, right_bound right) : left{std::move(left)}, right{std::move(right)} {}
55 auto contains(value_type const &x) const -> bool { return !(x < *this) && !(*this < x); }
57 [[nodiscard]] auto empty() const -> bool { return !(left < right); }
58
63 };
68
70 friend auto operator<(left_bound const &x, left_bound const &y) -> bool {
71 return x.bound < y.bound || (x.bound == y.bound && x.inclusive && !y.inclusive);
72 }
74 friend auto operator<=(left_bound const &x, left_bound const &y) -> bool {
75 return x.bound < y.bound || (x.bound == y.bound && (x.inclusive || !y.inclusive));
76 }
85 friend auto operator<(left_bound const &x, right_bound const &y) -> bool {
86 return x.bound < y.bound || (x.bound == y.bound && x.inclusive && y.inclusive);
87 }
88
90 friend auto operator<(right_bound const &x, right_bound const &y) -> bool {
91 return x.bound < y.bound || (y.bound == x.bound && !x.inclusive && y.inclusive);
92 }
94 friend auto operator<=(right_bound const &x, right_bound const &y) -> bool {
95 return x.bound < y.bound || (y.bound == x.bound && (!x.inclusive || y.inclusive));
96 }
105 friend auto operator<(right_bound const &x, left_bound const &y) -> bool {
106 return x.bound < y.bound || (y.bound == x.bound && !x.inclusive && !y.inclusive);
107 }
108
110 friend auto operator<(interval const &x, interval const &y) -> bool { return x.right < y.left; }
112 friend auto operator<(value_type const &x, interval const &y) -> bool {
113 return x < y.left.bound || (y.left.bound == x && !y.left.inclusive);
114 }
116 friend auto operator<(interval const &x, value_type const &y) -> bool {
117 return x.right.bound < y || (y == x.right.bound && !x.right.inclusive);
118 }
119
121 interval_set() = default;
123 ~interval_set() = default;
124
126 interval_set(interval_set const &other) = default;
128 auto operator=(interval_set const &other) -> interval_set & = default;
129
131 interval_set(interval_set &&other) noexcept = default;
133 auto operator=(interval_set &&other) noexcept -> interval_set & = default;
134
136 interval_set(std::initializer_list<interval> list) {
137 for (auto &x : list) {
138 add(x);
139 }
140 }
141
147 void reserve(size_t n) { vec_.reserve(n); }
148
150 auto release() -> interval_vector { return std::move(vec_); }
151
156 auto add(interval const &x) -> interval_set & {
157 if (!x.empty()) {
158 auto it = std::lower_bound(vec_.begin(), vec_.end(), x);
159 if (it == vec_.end()) {
160 vec_.emplace_back(x);
161 } else {
162 auto jt = std::upper_bound(it, vec_.end(), x);
163 if (it == jt) {
164 vec_.emplace(it, x);
165 } else {
166 it->left = std::min(x.left, it->left);
167 it->right = std::max(x.right, (jt - 1)->right);
168 vec_.erase(it + 1, jt);
169 }
170 }
171 }
172 return *this;
173 }
174
179 auto remove(interval const &x) -> interval_set & {
180 if (!x.empty()) {
181 auto it = std::lower_bound(vec_.begin(), vec_.end(), x);
182 if (it != vec_.end()) {
183 auto jt = std::upper_bound(it, vec_.end(), x);
184 if (it + 1 == jt) {
185 auto r = interval{left_bound{x.right}, it->right};
186 it->right = right_bound{x.left};
187 if (it->empty()) {
188 if (r.empty()) {
189 vec_.erase(it);
190 } else {
191 *it = r;
192 }
193 } else if (!r.empty()) {
194 vec_.emplace(it + 1, r);
195 }
196 } else if (it != jt) {
197 it->right = right_bound{x.left};
198 (jt - 1)->left = left_bound{x.right};
199 vec_.erase(it + !it->empty(), jt - !(jt - 1)->empty());
200 }
201 }
202 }
203 return *this;
204 }
205
210 [[nodiscard]] auto contains(interval const &x) const -> bool {
211 if (x.empty()) {
212 return true;
213 }
214 for (auto &y : vec_) {
215 if (x.right <= y.right) {
216 return y.left <= x.left;
217 }
218 }
219 return false;
220 }
221
226 [[nodiscard]] auto contains(T const &x) const -> bool {
227 for (auto &y : vec_) {
228 if (!(y < x)) {
229 return !(x < y);
230 }
231 }
232 return false;
233 }
234
239 [[nodiscard]] auto intersects(interval const &x) const -> bool {
240 if (!x.empty()) {
241 for (auto &y : vec_) {
242 if (x.left < y.right) {
243 return y.left < x.right;
244 }
245 }
246 }
247 return false;
248 }
249
251 [[nodiscard]] auto empty() const -> bool { return vec_.empty(); }
252
254 [[nodiscard]] auto size() const -> size_t { return vec_.size(); }
255
257 [[nodiscard]] auto front() const -> interval const & { return vec_.front(); }
258
260 [[nodiscard]] auto back() const -> interval const & { return vec_.back(); }
261
263 [[nodiscard]] auto begin() const -> iterator { return vec_.begin(); }
264
266 [[nodiscard]] auto end() const -> iterator { return vec_.end(); }
267
269 void clear() { return vec_.clear(); }
270
272 [[nodiscard]] auto intersect(interval_set const &set) const -> interval_set {
273 auto it = vec_.begin();
274 interval_set intersection;
275 for (auto &x : set.vec_) {
276 for (; it != vec_.end() && it->right < x.left; ++it) {
277 }
278 for (; it != vec_.end() && it->right <= x.right; ++it) {
279 intersection.vec_.emplace_back(interval{std::max(it->left, x.left), it->right});
280 }
281 if (it != vec_.end() && it->left < x.right) {
282 intersection.vec_.emplace_back(interval{std::max(it->left, x.left), x.right});
283 }
284 }
285 return intersection;
286 }
287
289 auto difference(interval_set const &set) const -> interval_set {
290 auto it = set.vec_.begin();
292 for (auto &x : vec_) {
293 interval current = x;
294 for (; it != set.vec_.end() && it->right < current.left; ++it) {
295 }
296 for (; it != set.vec_.end() && it->right <= current.right; ++it) {
297 if (current.left < it->left) {
298 difference.vec_.emplace_back(current);
299 difference.vec_.back().right = right_bound{it->left};
300 }
301 current.left = left_bound{it->right};
302 }
303 if (it != set.vec_.end() && it->left < current.right) {
304 current.right = right_bound{it->left};
305 }
306 if (current.left < current.right) {
307 difference.vec_.emplace_back(current);
308 }
309 }
310 return difference;
311 }
312
313 private:
314 interval_vector vec_;
315};
316
318
319} // namespace CppClingo::Util
A set of intervals.
Definition interval_set.hh:18
friend auto operator<=(right_bound const &x, right_bound const &y) -> bool
Right bound x is smaller than or equal to right bound y.
Definition interval_set.hh:94
friend auto operator<(left_bound const &x, left_bound const &y) -> bool
Left bound x is smaller than left bound y.
Definition interval_set.hh:70
auto size() const -> size_t
Get the size of the set.
Definition interval_set.hh:254
auto operator=(interval_set const &other) -> interval_set &=default
The default copy assignment.
friend auto operator<(left_bound const &x, right_bound const &y) -> bool
There is a gap between x and y.
Definition interval_set.hh:85
auto front() const -> interval const &
Get the first interval in the set.
Definition interval_set.hh:257
auto difference(interval_set const &set) const -> interval_set
Compute the difference between two interval sets.
Definition interval_set.hh:289
auto release() -> interval_vector
Releases the underlying vector.
Definition interval_set.hh:150
friend auto operator<(right_bound const &x, right_bound const &y) -> bool
Right bound x is smaller than right bound y.
Definition interval_set.hh:90
auto remove(interval const &x) -> interval_set &
Subtract the given interval from the set.
Definition interval_set.hh:179
auto contains(T const &x) const -> bool
Check if the set contains the given value.
Definition interval_set.hh:226
friend auto operator<(interval const &x, value_type const &y) -> bool
Interval x is before value y.
Definition interval_set.hh:116
friend auto operator<(right_bound const &x, left_bound const &y) -> bool
There is a gap between x and y.
Definition interval_set.hh:105
interval_set(interval_set const &other)=default
The default copy constructor.
auto back() const -> interval const &
Get the last interval in the set.
Definition interval_set.hh:260
auto end() const -> iterator
Get an iterator to the end of the set.
Definition interval_set.hh:266
auto intersect(interval_set const &set) const -> interval_set
Compute the intersection of two interval sets.
Definition interval_set.hh:272
auto contains(interval const &x) const -> bool
Check if the set contains the given interval.
Definition interval_set.hh:210
interval_set(interval_set &&other) noexcept=default
The default move constructor.
friend auto operator<(interval const &x, interval const &y) -> bool
Interval x is before interval y.
Definition interval_set.hh:110
friend auto operator<(value_type const &x, interval const &y) -> bool
Value x is before interval y.
Definition interval_set.hh:112
typename interval_vector::const_iterator iterator
An iterator over the intervals in the set.
Definition interval_set.hh:67
interval_set()=default
Construct an empty interval set.
auto intersects(interval const &x) const -> bool
Check if the set intersects the given interval.
Definition interval_set.hh:239
void clear()
Clear the set.
Definition interval_set.hh:269
~interval_set()=default
Destroy the interval set.
auto empty() const -> bool
Check if the set is empty.
Definition interval_set.hh:251
auto add(interval const &x) -> interval_set &
Add the given interval to the set.
Definition interval_set.hh:156
auto operator=(interval_set &&other) noexcept -> interval_set &=default
The default copy assignment.
auto begin() const -> iterator
Get an iterator to the beginning of the set.
Definition interval_set.hh:263
void reserve(size_t n)
Reserve space for at least n elements.
Definition interval_set.hh:147
small_vector< interval > interval_vector
The vector used to store intervals.
Definition interval_set.hh:65
interval_set(std::initializer_list< interval > list)
Construct an interval set containing the given intervals.
Definition interval_set.hh:136
T value_type
The value type used as bounds.
Definition interval_set.hh:21
friend auto operator<=(left_bound const &x, left_bound const &y) -> bool
Left bound x is smaller than or equal to left bound y.
Definition interval_set.hh:74
void reserve(size_t n)
Reserve space for at least n elements.
Definition small_vector.hh:185
auto front() -> reference
Get the first element in the vector.
Definition small_vector.hh:202
void emplace(const_iterator loc, U &&...args)
Emplace an element before the given iterator.
Definition small_vector.hh:253
interval const * const_iterator
The const iterator type.
Definition small_vector.hh:33
auto begin() -> iterator
Get an iterator to the beginning of the vector.
Definition small_vector.hh:135
void emplace_back(U &&...args)
Emplace an element after the last element.
Definition small_vector.hh:271
auto end() -> iterator
Get an iterator to the end of the vector.
Definition small_vector.hh:147
auto back() -> reference
Get the last element in the vector.
Definition small_vector.hh:214
auto erase(iterator it) -> iterator
Erase the given element.
Definition small_vector.hh:226
auto empty() const -> bool
Check if the vector is empty.
Definition small_vector.hh:124
auto size() const -> size_t
Get the size of the vector.
Definition small_vector.hh:116
void clear() noexcept
Clear the vector.
Definition small_vector.hh:298
An interval determined by a left and a right bound.
Definition interval_set.hh:51
constexpr interval(left_bound left, right_bound right)
Construct the bound.
Definition interval_set.hh:53
auto empty() const -> bool
Whether the interval is empty.
Definition interval_set.hh:57
right_bound right
The right bound of the interval.
Definition interval_set.hh:62
left_bound left
The left bound of the interval.
Definition interval_set.hh:60
auto contains(value_type const &x) const -> bool
Whether the interval contains the given value.
Definition interval_set.hh:55
A left bound of an interval.
Definition interval_set.hh:25
value_type bound
The value of the bound.
Definition interval_set.hh:32
left_bound(right_bound const &x)
Construct the bound from a right bound.
Definition interval_set.hh:29
bool inclusive
Whether the bound is open (!inclusive) or closed (inclusive).
Definition interval_set.hh:34
constexpr left_bound(value_type bound, bool inclusive)
Construct the bound.
Definition interval_set.hh:27
A right bound of an interval.
Definition interval_set.hh:38
constexpr right_bound(value_type bound, bool inclusive)
Construct the bound.
Definition interval_set.hh:40
bool inclusive
Whether the bound is open (!inclusive) or closed (inclusive).
Definition interval_set.hh:47
value_type bound
The value of the bound.
Definition interval_set.hh:45
right_bound(left_bound const &x)
Construct the bound from a left bound.
Definition interval_set.hh:42