this repo has no description
1/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
2/*
3 * Main authors:
4 * Guido Tack <tack@gecode.org>
5 * Gabor Szokoli <szokoli@gecode.org>
6 * Christian Schulte <schulte@gecode.org>
7 *
8 * Copyright:
9 * Guido Tack, 2004
10 * Christian Schulte, 2004
11 * Gabor Szokoli, 2004
12 *
13 * This file is part of Gecode, the generic constraint
14 * development environment:
15 * http://www.gecode.org
16 *
17 * Permission is hereby granted, free of charge, to any person obtaining
18 * a copy of this software and associated documentation files (the
19 * "Software"), to deal in the Software without restriction, including
20 * without limitation the rights to use, copy, modify, merge, publish,
21 * distribute, sublicense, and/or sell copies of the Software, and to
22 * permit persons to whom the Software is furnished to do so, subject to
23 * the following conditions:
24 *
25 * The above copyright notice and this permission notice shall be
26 * included in all copies or substantial portions of the Software.
27 *
28 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
29 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
30 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
31 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
32 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
33 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
34 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
35 *
36 */
37
38namespace Gecode { namespace Set {
39
40 /*
41 * BndSet
42 *
43 */
44
45 forceinline
46 BndSet::BndSet(void) :
47 first(nullptr), last(nullptr), _size(0), _card(0) {}
48
49 forceinline RangeList*
50 BndSet::fst(void) const {
51 return first;
52 }
53
54 forceinline RangeList*
55 BndSet::lst(void) const {
56 return last;
57 }
58
59 forceinline void
60 BndSet::dispose(Space& home) {
61 if (fst()!=nullptr)
62 fst()->dispose(home,lst());
63 }
64
65 forceinline void
66 BndSet::fst(RangeList* f) {
67 first = f;
68 }
69
70 forceinline void
71 BndSet::lst(RangeList* l) {
72 last = l;
73 }
74
75 forceinline
76 BndSet::BndSet(Space& home, int mn, int mx) {
77 if (mn>mx) {
78 fst(nullptr); lst(nullptr); _size = 0;
79 } else {
80 RangeList* p =
81 new (home) RangeList(mn,mx,nullptr);
82 fst(p); lst(p);
83 _size = static_cast<unsigned int>(mx-mn+1);
84 }
85 }
86
87 forceinline RangeList*
88 BndSet::ranges(void) const {
89 return fst();
90 }
91
92 forceinline unsigned int
93 BndSet::size(void) const {
94 return _size;
95 }
96
97 forceinline bool
98 BndSet::empty(void) const {
99 return (_size==0);
100 }
101
102 forceinline int
103 BndSet::min(void) const {
104 if (fst()==nullptr)
105 return MIN_OF_EMPTY;
106 else
107 return fst()->min();
108 }
109
110 forceinline int
111 BndSet::max(void) const {
112 if (lst()==nullptr)
113 return MAX_OF_EMPTY;
114 else
115 return lst()->max();
116 }
117
118 // nth smallest element
119 forceinline int
120 BndSet::minN(unsigned int n) const {
121 for (RangeList* c = fst(); c != nullptr; c = c->next()) {
122 if (c->width() > n)
123 return static_cast<int>(c->min() + n);
124 n -= c->width();
125 }
126 return MIN_OF_EMPTY;
127 }
128
129 forceinline unsigned int
130 BndSet::card(void) const {
131 return _card;
132 }
133
134 forceinline void
135 BndSet::card(unsigned int c) {
136 _card = c;
137 }
138
139 forceinline void
140 BndSet::update(Space& home, BndSet& d) {
141 if (d.fst() == fst())
142 return;
143 if (fst() != nullptr)
144 fst()->dispose(home,lst());
145 _size = d.size();
146 if (_size == 0) {
147 fst(nullptr); lst(nullptr);
148 return;
149 }
150
151 int n=0;
152 for (RangeList* c = d.fst(); c != nullptr; c = c->next())
153 n++;
154
155 RangeList* r = home.alloc<RangeList>(n);
156 fst(r); lst(r+n-1);
157
158 {
159 RangeList* c = d.fst();
160 for (int i=0; i<n; i++) {
161 r[i].min(c->min());
162 r[i].max(c->max());
163 r[i].next(&r[i+1]);
164 c = c->next();
165 }
166 }
167 r[n-1].next(nullptr);
168 }
169
170 template<class I> forceinline bool
171 BndSet::overwrite(Space& home, I& ri) {
172 // Is new domain empty?
173 if (!ri()) {
174 //Was it empty?
175 if (fst()==nullptr)
176 return false;
177 fst()->dispose(home,lst());
178 _size=0; fst(nullptr); lst(nullptr);
179 return true;
180 }
181
182 RangeList* f =
183 new (home) RangeList(ri.min(),ri.max(),nullptr);
184 RangeList* l = f;
185 unsigned int s = ri.width();
186
187 ++ri;
188
189 while (ri()) {
190 RangeList *n = new (home) RangeList(ri.min(),ri.max(),nullptr);
191 l->next(n);
192 l=n;
193 s += ri.width();
194 ++ri;
195 }
196
197 if (fst() != nullptr)
198 fst()->dispose(home,lst());
199 fst(f); lst(l);
200
201 // If the size did not change, nothing changed, as overwriting
202 // must not at the same time include and exclude elements.
203 if (size() == s)
204 return false;
205
206 _size = s;
207 return true;
208 }
209
210 forceinline void
211 BndSet::become(Space& home, const BndSet& that) {
212 if (fst()!=nullptr) {
213 assert(lst()!=nullptr);
214 assert(fst()!= that.fst());
215 fst()->dispose(home,lst());
216 }
217 fst(that.fst());
218 lst(that.lst());
219 _size = that.size();
220 assert(isConsistent());
221 }
222
223 forceinline bool
224 BndSet::in(int i) const {
225 for (RangeList* c = fst(); c != nullptr; c = c->next()) {
226 if (c->min() <= i && c->max() >= i)
227 return true;
228 if (c->min() > i)
229 return false;
230 }
231 return false;
232 }
233
234 /*
235 * Range iterator for BndSets
236 *
237 */
238
239 forceinline
240 BndSetRanges::BndSetRanges(void) {}
241
242 forceinline
243 BndSetRanges::BndSetRanges(const BndSet& s)
244 : Iter::Ranges::RangeList(s.ranges()) {}
245
246 forceinline void
247 BndSetRanges::init(const BndSet& s) {
248 Iter::Ranges::RangeList::init(s.ranges());
249 }
250
251 /*
252 * GLBndSet
253 *
254 */
255
256 forceinline
257 GLBndSet::GLBndSet(void) {}
258
259 forceinline
260 GLBndSet::GLBndSet(Space&) {}
261
262 forceinline
263 GLBndSet::GLBndSet(Space& home, int mi, int ma)
264 : BndSet(home,mi,ma) {}
265
266 forceinline
267 GLBndSet::GLBndSet(Space& home, const IntSet& s)
268 : BndSet(home,s) {}
269
270 forceinline void
271 GLBndSet::init(Space& home) {
272 dispose(home);
273 fst(nullptr);
274 lst(nullptr);
275 _size = 0;
276 }
277
278 forceinline bool
279 GLBndSet::include(Space& home, int mi, int ma, SetDelta& d) {
280 assert(ma >= mi);
281 if (fst()==nullptr) {
282 RangeList* p = new (home) RangeList(mi,ma,nullptr);
283 fst(p);
284 lst(p);
285 _size=static_cast<unsigned int>(ma-mi+1);
286 d._glbMin = mi;
287 d._glbMax = ma;
288 return true;
289 }
290 bool ret = include_full(home, mi, ma, d);
291 assert(isConsistent());
292 return ret;
293 }
294
295 template<class I> bool
296 GLBndSet::includeI(Space& home, I& i) {
297 if (!i())
298 return false;
299 BndSetRanges j(*this);
300 Iter::Ranges::Union<BndSetRanges,I> ij(j,i);
301 bool me = overwrite(home, ij);
302 assert(isConsistent());
303 return me;
304 }
305
306
307 /*
308 * LUBndSet
309 *
310 */
311
312 forceinline
313 LUBndSet::LUBndSet(void) {}
314
315 forceinline
316 LUBndSet::LUBndSet(Space& home)
317 : BndSet(home,Limits::min,Limits::max) {}
318
319 forceinline
320 LUBndSet::LUBndSet(Space& home, int mi, int ma)
321 : BndSet(home,mi,ma) {}
322
323 forceinline
324 LUBndSet::LUBndSet(Space& home, const IntSet& s)
325 : BndSet(home,s) {}
326
327 forceinline void
328 LUBndSet::init(Space& home) {
329 RangeList *p =
330 new (home) RangeList(Limits::min,
331 Limits::max,
332 nullptr);
333 fst(p);
334 lst(p);
335 _size = Limits::card;
336 }
337
338 forceinline bool
339 LUBndSet::exclude(Space& home, int mi, int ma, SetDelta& d) {
340 assert(ma >= mi);
341 if ((mi > max()) || (ma < min())) { return false; }
342 if (mi <= min() && ma >= max() ) { //the range covers the whole set
343 d._lubMin = min();
344 d._lubMax = max();
345 fst()->dispose(home,lst()); fst(nullptr); lst(nullptr);
346 _size=0;
347 return true;
348 }
349 bool ret = exclude_full(home, mi, ma, d);
350 assert(isConsistent());
351 return ret;
352 }
353
354 forceinline bool
355 LUBndSet::intersect(Space& home, int mi, int ma) {
356 assert(ma >= mi);
357 if ((mi <= min()) && (ma >= max())) { return false; }
358 if (_size == 0) return false;
359 if (ma < min() || mi > max() ) { // empty the whole set
360 fst()->dispose(home,lst()); fst(nullptr); lst(nullptr);
361 _size=0;
362 return true;
363 }
364 bool ret = intersect_full(home, mi, ma);
365 assert(isConsistent());
366 return ret;
367 }
368
369 template<class I> bool
370 LUBndSet::intersectI(Space& home, I& i) {
371 if (fst()==nullptr) { return false; }
372 if (!i()) {
373 fst()->dispose(home,lst()); fst(nullptr); lst(nullptr);
374 _size=0;
375 return true;
376 }
377 BndSetRanges j(*this);
378 Iter::Ranges::Inter<BndSetRanges,I> ij(j,i);
379 bool ret = overwrite(home, ij);
380 assert(isConsistent());
381 return ret;
382 }
383
384 template<class I> bool
385 LUBndSet::excludeI(Space& home, I& i) {
386 if (!i()) { return false; }
387 BndSetRanges j(*this);
388 Iter::Ranges::Diff<BndSetRanges,I> ij(j,i);
389 bool ret = overwrite(home, ij);
390 assert(isConsistent());
391 return ret;
392 }
393
394 forceinline void
395 LUBndSet::excludeAll(Space& home) {
396 fst()->dispose(home,lst()); fst(nullptr); lst(nullptr);
397 _size=0;
398 }
399
400 /*
401 * A complement iterator spezialized for the BndSet limits
402 *
403 */
404 template<class I>
405 RangesCompl<I>::RangesCompl(void) {}
406
407 template<class I>
408 RangesCompl<I>::RangesCompl(I& i)
409 : Iter::Ranges::Compl<Limits::min,
410 Limits::max,
411 I>(i) {}
412
413 template<class I> void
414 RangesCompl<I>::init(I& i) {
415 Iter::Ranges::Compl<Limits::min,
416 Limits::max,I>::init(i);
417 }
418
419}}
420
421// STATISTICS: set-var
422