Generated on for Gecode by doxygen 1.15.0
int.cpp
Go to the documentation of this file.
1/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
2/*
3 * Main authors:
4 * Christian Schulte <schulte@gecode.dev>
5 *
6 * Contributing authors:
7 * Mikael Zayenz Lagerkvist <lagerkvist@gecode.dev>
8 *
9 * Copyright:
10 * Christian Schulte, 2002
11 * Mikael Zayenz Lagerkvist, 2026
12 *
13 * This file is part of Gecode, the generic constraint
14 * development environment:
15 * http://www.gecode.dev
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
38#include <gecode/int.hh>
39
40namespace Gecode { namespace Int {
41
42 forceinline bool
43 IntVarImp::closer_min(int n) const {
44 unsigned int l = static_cast<unsigned int>(n) -
45 static_cast<unsigned int>(dom.min());
46 unsigned int r = static_cast<unsigned int>(dom.max()) -
47 static_cast<unsigned int>(n);
48 return l < r;
49 }
50
51 int
52 IntVarImp::med(void) const {
53 // Computes the median
54 if (fst() == nullptr)
55 return (dom.min()+dom.max())/2 - ((dom.min()+dom.max())%2 < 0 ? 1 : 0);
56 unsigned int i = size() / 2;
57 if (size() % 2 == 0)
58 i--;
59 const RangeList* p = nullptr;
60 const RangeList* c = fst();
61 while (i >= c->width()) {
62 i -= c->width();
63 const RangeList* n=c->next(p); p=c; c=n;
64 }
65 return c->min() + static_cast<int>(i);
66 }
67
68 bool
69 IntVarImp::in_full(int m) const {
70 if (closer_min(m)) {
71 const RangeList* p = nullptr;
72 const RangeList* c = fst();
73 while (m > c->max()) {
74 const RangeList* n=c->next(p); p=c; c=n;
75 }
76 return (m >= c->min());
77 } else {
78 const RangeList* n = nullptr;
79 const RangeList* c = lst();
80 while (m < c->min()) {
81 const RangeList* p=c->prev(n); n=c; c=p;
82 }
83 return (m <= c->max());
84 }
85 }
86
87 /*
88 * "Standard" tell operations
89 *
90 */
91
93 IntVarImp::lq_full(Space& home, int m) {
94 assert((m >= dom.min()) && (m <= dom.max()));
95 int old_max = dom.max();
97 if (range()) { // Is already range...
98 dom.max(m);
99 if (assigned()) me = ME_INT_VAL;
100 } else if (m < fst()->next(nullptr)->min()) { // Becomes range...
101 dom.max(std::min(m,fst()->max()));
102 fst()->dispose(home,nullptr,lst());
103 fst(nullptr); holes = 0;
104 if (assigned()) me = ME_INT_VAL;
105 } else { // Stays non-range...
106 RangeList* n = nullptr;
107 RangeList* c = lst();
108 unsigned int h = 0;
109 while (m < c->min()) {
110 RangeList* p = c->prev(n); c->fix(n);
111 h += static_cast<unsigned int>(c->min()) -
112 static_cast<unsigned int>(p->max()) - 1U;
113 n=c; c=p;
114 }
115 holes -= h;
116 int max_c = std::min(m,c->max());
117 dom.max(max_c); c->max(max_c);
118 if (c != lst()) {
119 n->dispose(home,lst());
120 c->next(n,nullptr); lst(c);
121 }
122 }
123 IntDelta d(dom.max()+1,old_max);
124 return notify(home,me,d);
125 }
126
128 IntVarImp::gq_full(Space& home, int m) {
129 assert((m >= dom.min()) && (m <= dom.max()));
130 int old_min = dom.min();
132 if (range()) { // Is already range...
133 dom.min(m);
134 if (assigned()) me = ME_INT_VAL;
135 } else if (m > lst()->prev(nullptr)->max()) { // Becomes range...
136 dom.min(std::max(m,lst()->min()));
137 fst()->dispose(home,nullptr,lst());
138 fst(nullptr); holes = 0;
139 if (assigned()) me = ME_INT_VAL;
140 } else { // Stays non-range...
141 RangeList* p = nullptr;
142 RangeList* c = fst();
143 unsigned int h = 0;
144 while (m > c->max()) {
145 RangeList* n = c->next(p); c->fix(n);
146 h += static_cast<unsigned int>(n->min()) -
147 static_cast<unsigned int>(c->max()) - 1U;
148 p=c; c=n;
149 }
150 holes -= h;
151 int min_c = std::max(m,c->min());
152 dom.min(min_c); c->min(min_c);
153 if (c != fst()) {
154 fst()->dispose(home,p);
155 c->prev(p,nullptr); fst(c);
156 }
157 }
158 IntDelta d(old_min,dom.min()-1);
159 return notify(home,me,d);
160 }
161
163 IntVarImp::eq_full(Space& home, int m) {
164 dom.min(m); dom.max(m);
165 if (!range()) {
166 bool failed = false;
167 RangeList* p = nullptr;
168 RangeList* c = fst();
169 while (m > c->max()) {
170 RangeList* n=c->next(p); c->fix(n); p=c; c=n;
171 }
172 if (m < c->min())
173 failed = true;
174 while (c != nullptr) {
175 RangeList* n=c->next(p); c->fix(n); p=c; c=n;
176 }
177 assert(p == lst());
178 fst()->dispose(home,p);
179 fst(nullptr); holes = 0;
180 if (failed)
181 return fail(home);
182 }
183 IntDelta d;
184 return notify(home,ME_INT_VAL,d);
185 }
186
188 IntVarImp::nq_full(Space& home, int m) {
189 assert(!((m < dom.min()) || (m > dom.max())));
191 if (range()) {
192 if ((m == dom.min()) && (m == dom.max()))
193 return fail(home);
194 if (m == dom.min()) {
195 dom.min(m+1);
197 } else if (m == dom.max()) {
198 dom.max(m-1);
200 } else {
201 RangeList* f = new (home) RangeList(dom.min(),m-1);
202 RangeList* l = new (home) RangeList(m+1,dom.max());
203 f->prevnext(nullptr,l);
204 l->prevnext(f,nullptr);
205 fst(f); lst(l); holes = 1;
206 }
207 } else if (m < fst()->next(nullptr)->min()) { // Concerns the first range...
208 int f_max = fst()->max();
209 if (m > f_max)
210 return ME_INT_NONE;
211 int f_min = dom.min();
212 if ((m == f_min) && (m == f_max)) {
213 RangeList* f_next = fst()->next(nullptr);
214 dom.min(f_next->min());
215 if (f_next == lst()) { // Turns into range
216 // Works as at the ends there are only nullptr pointers
217 fst()->dispose(home,f_next);
218 fst(nullptr); holes = 0;
220 } else { // Remains non-range
221 f_next->prev(fst(),nullptr);
222 fst()->dispose(home); fst(f_next);
223 holes -= static_cast<unsigned int>(dom.min()) -
224 static_cast<unsigned int>(f_min) - 1U;
225 me = ME_INT_BND;
226 }
227 } else if (m == f_min) {
228 dom.min(m+1); fst()->min(m+1);
229 me = ME_INT_BND;
230 } else if (m == f_max) {
231 fst()->max(m-1); holes += 1;
232 } else {
233 // Create new hole
234 RangeList* f = new (home) RangeList(f_min,m-1);
235 f->prevnext(nullptr,fst());
236 fst()->min(m+1); fst()->prev(nullptr,f);
237 fst(f); holes += 1;
238 }
239 } else if (m > lst()->prev(nullptr)->max()) { // Concerns the last range...
240 int l_min = lst()->min();
241 if (m < l_min)
242 return ME_INT_NONE;
243 int l_max = dom.max();
244 if ((m == l_min) && (m == l_max)) {
245 RangeList* l_prev = lst()->prev(nullptr);
246 dom.max(l_prev->max());
247 if (l_prev == fst()) {
248 // Turns into range
249 l_prev->dispose(home,lst());
250 fst(nullptr); holes = 0;
252 } else { // Remains non-range
253 l_prev->next(lst(),nullptr);
254 lst()->dispose(home); lst(l_prev);
255 holes -= static_cast<unsigned int>(l_max) -
256 static_cast<unsigned int>(dom.max()) - 1U;
257 me = ME_INT_BND;
258 }
259 } else if (m == l_max) {
260 dom.max(m-1); lst()->max(m-1);
261 me = ME_INT_BND;
262 } else if (m == l_min) {
263 lst()->min(m+1); holes += 1;
264 } else { // Create new hole
265 RangeList* l = new (home) RangeList(m+1,l_max);
266 l->prevnext(lst(),nullptr);
267 lst()->max(m-1); lst()->next(nullptr,l);
268 lst(l); holes += 1;
269 }
270 } else { // Concerns element in the middle of the list of ranges
271 RangeList* p;
272 RangeList* c;
273 RangeList* n;
274 if (closer_min(m)) {
275 assert(m > fst()->max());
276 p = nullptr;
277 c = fst();
278 do {
279 n=c->next(p); p=c; c=n;
280 } while (m > c->max());
281 if (m < c->min())
282 return ME_INT_NONE;
283 n=c->next(p);
284 } else {
285 assert(m < lst()->min());
286 n = nullptr;
287 c = lst();
288 do {
289 p=c->prev(n); n=c; c=p;
290 } while (m < c->min());
291 if (m > c->max())
292 return ME_INT_NONE;
293 p=c->prev(n);
294 }
295 assert((fst() != c) && (lst() != c));
296 assert((m >= c->min()) && (m <= c->max()));
297 holes += 1;
298 int c_min = c->min();
299 int c_max = c->max();
300 if ((c_min == m) && (c_max == m)) {
301 c->dispose(home);
302 p->next(c,n); n->prev(c,p);
303 } else if (c_min == m) {
304 c->min(m+1);
305 } else {
306 c->max(m-1);
307 if (c_max != m) {
308 RangeList* l = new (home) RangeList(m+1,c_max);
309 l->prevnext(c,n);
310 c->next(n,l);
311 n->prev(c,l);
312 }
313 }
314 }
315 IntDelta d(m,m);
316 return notify(home,me,d);
317 }
318
319
320
321 /*
322 * Copying variables
323 *
324 */
325
328 : IntVarImpBase(home,x), dom(x.dom.min(),x.dom.max()) {
329 holes = x.holes;
330 if (holes) {
331 int m = 1;
332 // Compute length
333 {
334 RangeList* s_p = x.fst();
335 RangeList* s_c = s_p->next(nullptr);
336 do {
337 m++;
338 RangeList* s_n = s_c->next(s_p); s_p=s_c; s_c=s_n;
339 } while (s_c != nullptr);
340 }
341 RangeList* d_c = home.alloc<RangeList>(m);
342 fst(d_c); lst(d_c+m-1);
343 d_c->min(x.fst()->min());
344 d_c->max(x.fst()->max());
345 d_c->prevnext(nullptr,nullptr);
346 RangeList* s_p = x.fst();
347 RangeList* s_c = s_p->next(nullptr);
348 do {
349 RangeList* d_n = d_c + 1;
350 d_c->next(nullptr,d_n);
351 d_n->prevnext(d_c,nullptr);
352 d_n->min(s_c->min()); d_n->max(s_c->max());
353 d_c = d_n;
354 RangeList* s_n=s_c->next(s_p); s_p=s_c; s_c=s_n;
355 } while (s_c != nullptr);
356 d_c->next(nullptr,nullptr);
357 } else {
358 fst(nullptr);
359 }
360 }
361
362 IntVarImp*
363 IntVarImp::perform_copy(Space& home) {
364 return new (home) IntVarImp(home,*this);
365 }
366
367 /*
368 * Dependencies
369 *
370 */
371 void
373 bool schedule) {
374 IntVarImpBase::subscribe(home,p,pc,dom.min()==dom.max(),schedule);
375 }
376
377 void
379 IntVarImpBase::reschedule(home,p,pc,dom.min()==dom.max());
380 }
381
382 void
384 IntVarImpBase::subscribe(home,a,dom.min()==dom.max(),fail);
385 }
386
387}}
388
389// STATISTICS: int-var
Base-class for advisors.
Definition core.hpp:1301
void subscribe(Gecode::Space &home, Gecode::Propagator &p, Gecode::PropCond pc, bool assigned, bool schedule)
Subscribe propagator p with propagation condition pc.
Definition var-imp.hpp:251
static void schedule(Gecode::Space &home, Gecode::Propagator &p, Gecode::ModEvent me)
Schedule propagator p.
Definition var-imp.hpp:260
IntVarImpBase(Gecode::Space &home, IntVarImpBase &x)
Constructor for cloning x.
Definition var-imp.hpp:247
void reschedule(Gecode::Space &home, Gecode::Propagator &p, Gecode::PropCond pc, bool assigned)
Re-schedule propagator p.
Definition var-imp.hpp:264
Gecode::ModEvent notify(Gecode::Space &home, Gecode::ModEvent me, Gecode::Delta &d)
Notify that variable implementation has been modified with modification event me and delta informatio...
Definition var-imp.hpp:269
Lists of ranges (intervals).
Definition var-imp.hpp:102
int min(void) const
Return minimum.
Definition int.hpp:106
void prevnext(RangeList *p, RangeList *n)
Set previous element to p and next element to n.
Definition int.hpp:78
RangeList * prev(const RangeList *n) const
Return previous element (from next n).
Definition int.hpp:74
RangeList * next(const RangeList *p) const
Return next element (from previous p).
Definition int.hpp:70
int max(void) const
Return maximum.
Definition int.hpp:110
void dispose(Space &home, RangeList *p, RangeList *l)
Free memory for all elements between this and l (inclusive).
Definition int.hpp:142
Integer variable implementation.
Definition var-imp.hpp:89
RangeList * lst(void) const
Return last element of rangelist.
Definition int.hpp:181
int med(void) const
Return median of domain (greatest element not greater than the median).
Definition int.cpp:52
bool assigned(void) const
Test whether variable is assigned.
Definition int.hpp:250
int max(void) const
Return maximum of domain.
Definition int.hpp:236
RangeList * fst(void) const
Return first element of rangelist.
Definition int.hpp:171
void subscribe(Space &home, Propagator &p, PropCond pc, bool schedule=true)
Subscribe propagator p with propagation condition pc to variable.
Definition int.cpp:372
unsigned int size(void) const
Return size (cardinality) of domain.
Definition int.hpp:261
int min(void) const
Return minimum of domain.
Definition int.hpp:232
RangeList dom
Domain information.
Definition var-imp.hpp:188
unsigned int holes
Size of holes in the domain.
Definition var-imp.hpp:200
bool range(void) const
Test whether domain is a range.
Definition int.hpp:246
IntVarImp(Space &home, IntVarImp &x)
Constructor for cloning x.
Definition int.cpp:327
void reschedule(Space &home, Propagator &p, PropCond pc)
Re-schedule propagator p.
Definition int.cpp:378
Base-class for propagators.
Definition core.hpp:1073
Lists of ranges (intervals).
Computation spaces.
Definition core.hpp:1775
T * alloc(long unsigned int n)
Allocate block of n objects of type T from space heap.
Definition core.hpp:2901
static ModEvent me(const ModEventDelta &med)
Definition core.hpp:4415
VarImp< Gecode::Int::IntVarImpConf > * next
Definition core.hpp:280
Finite domain integers.
Definition lastval.hh:52
const Gecode::ModEvent ME_INT_BND
Domain operation has changed the minimum or maximum of the domain.
Definition var-type.hpp:73
const Gecode::ModEvent ME_INT_VAL
Domain operation has resulted in a value (assigned variable).
Definition var-type.hpp:64
const Gecode::ModEvent ME_INT_DOM
Domain operation has changed the domain.
Definition var-type.hpp:80
const Gecode::ModEvent ME_INT_NONE
Domain operation has not changed domain.
Definition var-type.hpp:62
Gecode toplevel namespace
int PropCond
Type for propagation conditions.
Definition core.hpp:77
int ModEvent
Type for modification events.
Definition core.hpp:67
Gecode::IntSet d(v, 7)
const int r[4][2]
Definition dom.cpp:152
#define forceinline
Definition config.hpp:141