3
* Christian Schulte <schulte@gecode.org>
5
* Contributing authors:
6
* Guido Tack <tack@gecode.org>
9
* Christian Schulte, 2003
13
* $Date: 2005-10-31 11:02:00 +0100 (Mon, 31 Oct 2005) $ by $Author: schulte $
16
* This file is part of Gecode, the generic constraint
17
* development environment:
18
* http://www.gecode.org
20
* See the file "LICENSE" for information on usage and
21
* redistribution of this file, and for a
22
* DISCLAIMER OF ALL WARRANTIES.
26
namespace Gecode { namespace Int {
33
#define RL2PD(r) reinterpret_cast<ptrdiff_t>(r)
34
#define PD2RL(p) reinterpret_cast<RangeList*>(p)
37
IntVarImp::RangeList::RangeList(void) {}
40
IntVarImp::RangeList::RangeList(int min, int max)
41
: _min(min), _max(max) {}
44
IntVarImp::RangeList::RangeList(int min, int max, RangeList* p, RangeList* n)
45
: _min(min), _max(max) {
46
_next = PD2RL(RL2PD(p)^RL2PD(n));
49
forceinline IntVarImp::RangeList*
50
IntVarImp::RangeList::next(const RangeList* p) const {
51
return PD2RL(RL2PD(_next)^RL2PD(p));
53
forceinline IntVarImp::RangeList*
54
IntVarImp::RangeList::prev(const RangeList* n) const {
55
return PD2RL(RL2PD(_next)^RL2PD(n));
58
IntVarImp::RangeList::prevnext(RangeList* p, RangeList* n) {
59
_next = PD2RL(RL2PD(p)^RL2PD(n));
62
IntVarImp::RangeList::next(RangeList* o, RangeList* n) {
63
_next = PD2RL(RL2PD(_next)^(RL2PD(o)^RL2PD(n)));
66
IntVarImp::RangeList::prev(RangeList* o, RangeList* n) {
67
_next = PD2RL(RL2PD(_next)^(RL2PD(o)^RL2PD(n)));
70
IntVarImp::RangeList::fix(RangeList* n) {
75
IntVarImp::RangeList::min(int n) {
79
IntVarImp::RangeList::max(int n) {
84
IntVarImp::RangeList::min(void) const {
88
IntVarImp::RangeList::max(void) const {
91
forceinline unsigned int
92
IntVarImp::RangeList::width(void) const {
93
return _max - _min + 1;
98
IntVarImp::RangeList::operator delete(void*) {}
101
IntVarImp::RangeList::operator delete(void*, Space*) {
106
IntVarImp::RangeList::operator new(size_t s, Space* home) {
107
assert(s == sizeof(RangeList));
108
return home->fl_alloc<sizeof(RangeList)>();
112
IntVarImp::RangeList::dispose(Space* home, RangeList* p, RangeList* l) {
115
RangeList* n = c->next(p);
119
home->fl_dispose<sizeof(RangeList)>(this,l);
123
IntVarImp::RangeList::dispose(Space* home, RangeList* l) {
124
home->fl_dispose<sizeof(RangeList)>(this,l);
128
IntVarImp::RangeList::dispose(Space* home) {
129
home->fl_dispose<sizeof(RangeList)>(this,this);
136
* Mainitaining range lists for variable domain
140
forceinline IntVarImp::RangeList*
141
IntVarImp::fst(void) const {
142
return dom.next(NULL);
146
IntVarImp::fst(IntVarImp::RangeList* f) {
147
dom.prevnext(NULL,f);
150
forceinline IntVarImp::RangeList*
151
IntVarImp::lst(void) const {
156
IntVarImp::lst(IntVarImp::RangeList* l) {
161
* Creation of new variable implementations
166
IntVarImp::IntVarImp(Space* home, int min, int max)
167
: Variable<VTI_INT,PC_INT_DOM>(home),
168
dom(min,max,NULL,NULL), holes(0) {}
171
IntVarImp::IntVarImp(Space* home, const IntSet& d)
172
: Variable<VTI_INT,PC_INT_DOM>(home),
173
dom(d.min(),d.max()) {
176
RangeList* r = reinterpret_cast<RangeList*>
177
(home->alloc(sizeof(RangeList)*n));
179
unsigned int h = d.max()-d.min()+1;
180
for (int i = n; i--; ) {
182
r[i].min(d.min(i)); r[i].max(d.max(i));
183
r[i].prevnext(&r[i-1],&r[i+1]);
185
r[0].prev(&r[-1],NULL);
186
r[n-1].next(&r[n],NULL);
189
fst(NULL); holes = 0;
195
* Operations on integer variable implementations
200
IntVarImp::min(void) const {
204
IntVarImp::max(void) const {
208
IntVarImp::val(void) const {
209
assert(dom.min() == dom.max());
214
IntVarImp::range(void) const {
215
return fst() == NULL;
218
IntVarImp::assigned(void) const {
219
return dom.min() == dom.max();
223
forceinline unsigned int
224
IntVarImp::width(void) const {
228
forceinline unsigned int
229
IntVarImp::size(void) const {
230
return dom.width() - holes;
233
forceinline unsigned int
234
IntVarImp::regret_min(void) const {
236
return (dom.min() == dom.max()) ? 0 : 1;
237
} else if (dom.min() == fst()->max()) {
238
return fst()->next(NULL)->min()-dom.min();
243
forceinline unsigned int
244
IntVarImp::regret_max(void) const {
246
return (dom.min() == dom.max()) ? 0 : 1;
247
} else if (dom.max() == lst()->min()) {
248
return dom.max()-lst()->prev(NULL)->max();
262
IntVarImp::in(int n) const {
263
if ((n < dom.min()) || (n > dom.max()))
265
return (fst() == NULL) || in_full(n);
268
IntVarImp::in(double n) const {
269
if ((n < dom.min()) || (n > dom.max()))
271
return (fst() == NULL) || in_full(static_cast<int>(n));
276
* Accessing rangelists for iteration
280
forceinline const IntVarImp::RangeList*
281
IntVarImp::ranges_fwd(void) const {
282
return (fst() == NULL) ? &dom : fst();
285
forceinline const IntVarImp::RangeList*
286
IntVarImp::ranges_bwd(void) const {
287
return (fst() == NULL) ? &dom : lst();
293
* Tell operations (to be inlined: performing bounds checks first)
298
IntVarImp::gq(Space* home, int n) {
299
if (n <= dom.min()) return ME_INT_NONE;
300
if (n > dom.max()) return ME_INT_FAILED;
307
IntVarImp::gq(Space* home, double n) {
308
if (n <= dom.min()) return ME_INT_NONE;
309
if (n > dom.max()) return ME_INT_FAILED;
310
gq_full(home,static_cast<int>(n));
318
IntVarImp::lq(Space* home, int n) {
319
if (n >= dom.max()) return ME_INT_NONE;
320
if (n < dom.min()) return ME_INT_FAILED;
327
IntVarImp::lq(Space* home, double n) {
328
if (n >= dom.max()) return ME_INT_NONE;
329
if (n < dom.min()) return ME_INT_FAILED;
330
lq_full(home,static_cast<int>(n));
338
IntVarImp::eq(Space* home, int n) {
339
if ((n < dom.min()) || (n > dom.max()))
340
return ME_INT_FAILED;
341
if ((n == dom.min()) && (n == dom.max()))
344
if (dom.min() == Limits::Int::int_max+1)
345
return ME_INT_FAILED;
349
IntVarImp::eq(Space* home, double n) {
350
if ((n < dom.min()) || (n > dom.max()))
351
return ME_INT_FAILED;
352
if ((n == dom.min()) && (n == dom.max()))
354
eq_full(home,static_cast<int>(n));
355
if (dom.min() == Limits::Int::int_max+1)
356
return ME_INT_FAILED;
362
IntVarImp::nq(Space* home, int n) {
363
if ((n < dom.min()) || (n > dom.max())) return ME_INT_NONE;
364
return nq_full(home,n);
367
IntVarImp::nq(Space* home, double d) {
368
if ((d < dom.min()) || (d > dom.max())) return ME_INT_NONE;
369
return nq_full(home,static_cast<int>(d));
374
* Tell operations with respect to iterators
380
IntVarImp::narrow(Space* home, I& ri) {
381
// Is new domain empty?
383
return ME_INT_FAILED;
387
// Is new domain range?
389
// Remove possible rangelist (if it was not a range, the domain
390
// must have been narrowed!)
392
fst()->dispose(home,NULL,lst());
393
fst(NULL); holes = 0;
395
const int min1 = dom.min(); dom.min(min0);
396
const int max1 = dom.max(); dom.max(max0);
397
if ((min0 == min1) && (max0 == max1))
400
notify(home,ME_INT_VAL);
404
// Construct new rangelist
405
RangeList* f = new (home) RangeList(min0,max0,NULL,NULL);
407
unsigned int s = max0-min0+1;
409
RangeList* n = new (home) RangeList(ri.min(),ri.max(),l,NULL);
416
fst()->dispose(home,NULL,lst());
418
// Check for modification
421
const int min1 = dom.min(); min0 = f->min(); dom.min(min0);
422
const int max1 = dom.max(); max0 = l->max(); dom.max(max0);
424
if ((min0 == min1) && (max0 == max1)) {
425
notify(home,ME_INT_DOM);
429
notify(home,ME_INT_BND);
438
forceinline IntVarImp*
439
IntVarImp::copy(Space* home, bool share) {
440
return copied() ? static_cast<IntVarImp*>(forward())
441
: perform_copy(home,share);
447
* Boolean tell operations (assume not yet assigned 0/1 variable)
452
IntVarImp::t_zero_none(Space* home) {
453
assert((dom.min() == 0) && (dom.max() == 1));
455
notify_unmodified(home,ME_INT_VAL);
459
IntVarImp::t_one_none(Space* home) {
460
assert((dom.min() == 0) && (dom.max() == 1));
462
notify_unmodified(home,ME_INT_VAL);
467
* Forward range iterator for rangelists
472
IntVarImpFwd::IntVarImpFwd(void) {}
474
IntVarImpFwd::IntVarImpFwd(const IntVarImp* x)
475
: p(NULL), c(x->ranges_fwd()) {}
477
IntVarImpFwd::init(const IntVarImp* x) {
478
p=NULL; c=x->ranges_fwd();
482
IntVarImpFwd::operator()(void) const {
486
IntVarImpFwd::operator++(void) {
487
const IntVarImp::RangeList* n=c->next(p); p=c; c=n;
491
IntVarImpFwd::min(void) const {
495
IntVarImpFwd::max(void) const {
498
forceinline unsigned int
499
IntVarImpFwd::width(void) const {
505
* Backward range iterator for rangelists
510
IntVarImpBwd::IntVarImpBwd(void) {}
512
IntVarImpBwd::IntVarImpBwd(const IntVarImp* x)
513
: n(NULL), c(x->ranges_bwd()) {}
515
IntVarImpBwd::init(const IntVarImp* x) {
516
n=NULL; c=x->ranges_bwd();
520
IntVarImpBwd::operator()(void) const {
524
IntVarImpBwd::operator++(void) {
525
const IntVarImp::RangeList* p=c->prev(n); n=c; c=p;
529
IntVarImpBwd::min(void) const {
533
IntVarImpBwd::max(void) const {
536
forceinline unsigned int
537
IntVarImpBwd::width(void) const {
543
* More domain operations
548
IntVarImp::inter(Space* home, I& i) {
549
IntVarImpFwd j(this);
550
Iter::Ranges::Inter<I,IntVarImpFwd> ij(i,j);
551
return narrow(home,ij);
556
IntVarImp::minus(Space* home, I& i) {
557
IntVarImpFwd j(this);
558
Iter::Ranges::Diff<IntVarImpFwd,I> ij(j,i);
559
return narrow(home,ij);
564
// STATISTICS: int-var