this repo has no description
1/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
2/*
3 * Main authors:
4 * Christian Schulte <schulte@gecode.org>
5 *
6 * Copyright:
7 * Christian Schulte, 2003
8 *
9 * This file is part of Gecode, the generic constraint
10 * development environment:
11 * http://www.gecode.org
12 *
13 * Permission is hereby granted, free of charge, to any person obtaining
14 * a copy of this software and associated documentation files (the
15 * "Software"), to deal in the Software without restriction, including
16 * without limitation the rights to use, copy, modify, merge, publish,
17 * distribute, sublicense, and/or sell copies of the Software, and to
18 * permit persons to whom the Software is furnished to do so, subject to
19 * the following conditions:
20 *
21 * The above copyright notice and this permission notice shall be
22 * included in all copies or substantial portions of the Software.
23 *
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 *
32 */
33
34#include <gecode/int/linear/int-noview.hpp>
35
36namespace Gecode { namespace Int { namespace Linear {
37
38 /**
39 * \brief Test if only unit-coefficient arrays used
40 *
41 */
42 template<class P, class N>
43 forceinline bool
44 isunit(ViewArray<P>&, ViewArray<N>&) { return false; }
45 template<>
46 forceinline bool
47 isunit(ViewArray<IntView>&, ViewArray<IntView>&) { return true; }
48 template<>
49 forceinline bool
50 isunit(ViewArray<IntView>&, ViewArray<NoView>&) { return true; }
51 template<>
52 forceinline bool
53 isunit(ViewArray<NoView>&, ViewArray<IntView>&) { return true; }
54
55 /*
56 * Linear propagators
57 *
58 */
59 template<class Val, class P, class N, PropCond pc>
60 forceinline
61 Lin<Val,P,N,pc>::Lin(Home home, ViewArray<P>& x0, ViewArray<N>& y0, Val c0)
62 : Propagator(home), x(x0), y(y0), c(c0) {
63 x.subscribe(home,*this,pc);
64 y.subscribe(home,*this,pc);
65 }
66
67 template<class Val, class P, class N, PropCond pc>
68 forceinline
69 Lin<Val,P,N,pc>::Lin(Space& home, Lin<Val,P,N,pc>& p)
70 : Propagator(home,p), c(p.c) {
71 x.update(home,p.x);
72 y.update(home,p.y);
73 }
74
75 template<class Val, class P, class N, PropCond pc>
76 PropCost
77 Lin<Val,P,N,pc>::cost(const Space&, const ModEventDelta&) const {
78 return PropCost::linear(PropCost::LO, x.size()+y.size());
79 }
80
81 template<class Val, class P, class N, PropCond pc>
82 void
83 Lin<Val,P,N,pc>::reschedule(Space& home) {
84 x.reschedule(home,*this,pc);
85 y.reschedule(home,*this,pc);
86 }
87
88 template<class Val, class P, class N, PropCond pc>
89 forceinline size_t
90 Lin<Val,P,N,pc>::dispose(Space& home) {
91 x.cancel(home,*this,pc);
92 y.cancel(home,*this,pc);
93 (void) Propagator::dispose(home);
94 return sizeof(*this);
95 }
96
97 /*
98 * Reified linear propagators
99 *
100 */
101 template<class Val, class P, class N, PropCond pc, class Ctrl>
102 forceinline
103 ReLin<Val,P,N,pc,Ctrl>::ReLin
104 (Home home, ViewArray<P>& x, ViewArray<N>& y, Val c, Ctrl b0)
105 : Lin<Val,P,N,pc>(home,x,y,c), b(b0) {
106 b.subscribe(home,*this,PC_INT_VAL);
107 }
108
109 template<class Val, class P, class N, PropCond pc, class Ctrl>
110 forceinline
111 ReLin<Val,P,N,pc,Ctrl>::ReLin
112 (Space& home, ReLin<Val,P,N,pc,Ctrl>& p)
113 : Lin<Val,P,N,pc>(home,p) {
114 b.update(home,p.b);
115 }
116
117 template<class Val, class P, class N, PropCond pc, class Ctrl>
118 void
119 ReLin<Val,P,N,pc,Ctrl>::reschedule(Space& home) {
120 x.reschedule(home,*this,pc);
121 y.reschedule(home,*this,pc);
122 b.reschedule(home,*this,PC_INT_VAL);
123 }
124
125 template<class Val, class P, class N, PropCond pc, class Ctrl>
126 forceinline size_t
127 ReLin<Val,P,N,pc,Ctrl>::dispose(Space& home) {
128 b.cancel(home,*this,PC_BOOL_VAL);
129 (void) Lin<Val,P,N,pc>::dispose(home);
130 return sizeof(*this);
131 }
132
133 /*
134 * Computing bounds
135 *
136 */
137
138 template<class Val, class View>
139 void
140 bounds_p(ModEventDelta med, ViewArray<View>& x, Val& c, Val& sl, Val& su) {
141 int n = x.size();
142 if (IntView::me(med) == ME_INT_VAL) {
143 for (int i=n; i--; ) {
144 Val m = x[i].min();
145 if (x[i].assigned()) {
146 c -= m; x[i] = x[--n];
147 } else {
148 sl -= m; su -= x[i].max();
149 }
150 }
151 x.size(n);
152 } else {
153 for (int i=0; i<n; i++) {
154 sl -= x[i].min(); su -= x[i].max();
155 }
156 }
157 }
158
159 template<class Val, class View>
160 void
161 bounds_n(ModEventDelta med, ViewArray<View>& y, Val& c, Val& sl, Val& su) {
162 int n = y.size();
163 if (IntView::me(med) == ME_INT_VAL) {
164 for (int i=n; i--; ) {
165 Val m = y[i].max();
166 if (y[i].assigned()) {
167 c += m; y[i] = y[--n];
168 } else {
169 sl += m; su += y[i].min();
170 }
171 }
172 y.size(n);
173 } else {
174 for (int i=0; i<n; i++) {
175 sl += y[i].max(); su += y[i].min();
176 }
177 }
178 }
179
180
181 template<class Val, class P, class N>
182 ExecStatus
183 prop_bnd(Space& home, ModEventDelta med, Propagator& p,
184 ViewArray<P>& x, ViewArray<N>& y, Val& c) {
185 // Eliminate singletons
186 Val sl = 0;
187 Val su = 0;
188
189 bounds_p<Val,P>(med, x, c, sl, su);
190 bounds_n<Val,N>(med, y, c, sl, su);
191
192 if ((IntView::me(med) == ME_INT_VAL) && ((x.size() + y.size()) <= 1)) {
193 if (x.size() == 1) {
194 GECODE_ME_CHECK(x[0].eq(home,c));
195 return home.ES_SUBSUMED(p);
196 }
197 if (y.size() == 1) {
198 GECODE_ME_CHECK(y[0].eq(home,-c));
199 return home.ES_SUBSUMED(p);
200 }
201 return (c == static_cast<Val>(0)) ?
202 home.ES_SUBSUMED(p) : ES_FAILED;
203 }
204
205 sl += c; su += c;
206
207 const int mod_sl = 1;
208 const int mod_su = 2;
209
210 int mod = mod_sl | mod_su;
211
212 do {
213 if (mod & mod_sl) {
214 mod -= mod_sl;
215 // Propagate upper bound for positive variables
216 for (int i=0; i<x.size(); i++) {
217 const Val xi_max = x[i].max();
218 ModEvent me = x[i].lq(home,sl + x[i].min());
219 if (me_failed(me))
220 return ES_FAILED;
221 if (me_modified(me)) {
222 su += xi_max - x[i].max();
223 mod |= mod_su;
224 }
225 }
226 // Propagate lower bound for negative variables
227 for (int i=0; i<y.size(); i++) {
228 const Val yi_min = y[i].min();
229 ModEvent me = y[i].gq(home,y[i].max() - sl);
230 if (me_failed(me))
231 return ES_FAILED;
232 if (me_modified(me)) {
233 su += y[i].min() - yi_min;
234 mod |= mod_su;
235 }
236 }
237 }
238 if (mod & mod_su) {
239 mod -= mod_su;
240 // Propagate lower bound for positive variables
241 for (int i=0; i<x.size(); i++) {
242 const Val xi_min = x[i].min();
243 ModEvent me = x[i].gq(home,su + x[i].max());
244 if (me_failed(me))
245 return ES_FAILED;
246 if (me_modified(me)) {
247 sl += xi_min - x[i].min();
248 mod |= mod_sl;
249 }
250 }
251 // Propagate upper bound for negative variables
252 for (int i=0; i<y.size(); i++) {
253 const Val yi_max = y[i].max();
254 ModEvent me = y[i].lq(home,y[i].min() - su);
255 if (me_failed(me))
256 return ES_FAILED;
257 if (me_modified(me)) {
258 sl += y[i].max() - yi_max;
259 mod |= mod_sl;
260 }
261 }
262 }
263 } while (mod);
264
265 return (sl == su) ? home.ES_SUBSUMED(p) : ES_FIX;
266 }
267
268 /*
269 * Bound consistent linear equation
270 *
271 */
272
273 template<class Val, class P, class N>
274 forceinline
275 Eq<Val,P,N>::Eq(Home home, ViewArray<P>& x, ViewArray<N>& y, Val c)
276 : Lin<Val,P,N,PC_INT_BND>(home,x,y,c) {}
277
278 template<class Val, class P, class N>
279 ExecStatus
280 Eq<Val,P,N>::post(Home home, ViewArray<P>& x, ViewArray<N>& y, Val c) {
281 ViewArray<NoView> nva;
282 if (y.size() == 0) {
283 (void) new (home) Eq<Val,P,NoView>(home,x,nva,c);
284 } else if (x.size() == 0) {
285 (void) new (home) Eq<Val,N,NoView>(home,y,nva,-c);
286 } else {
287 (void) new (home) Eq<Val,P,N>(home,x,y,c);
288 }
289 return ES_OK;
290 }
291
292
293 template<class Val, class P, class N>
294 forceinline
295 Eq<Val,P,N>::Eq(Space& home, Eq<Val,P,N>& p)
296 : Lin<Val,P,N,PC_INT_BND>(home,p) {}
297
298 /**
299 * \brief Rewriting of equality to binary propagators
300 *
301 */
302 template<class Val, class P, class N>
303 forceinline Actor*
304 eqtobin(Space&, Propagator&, ViewArray<P>&, ViewArray<N>&, Val) {
305 return nullptr;
306 }
307 template<class Val>
308 forceinline Actor*
309 eqtobin(Space& home, Propagator& p,
310 ViewArray<IntView>& x, ViewArray<NoView>&, Val c) {
311 assert(x.size() == 2);
312 return new (home) EqBin<Val,IntView,IntView>
313 (home,p,x[0],x[1],c);
314 }
315 template<class Val>
316 forceinline Actor*
317 eqtobin(Space& home, Propagator& p,
318 ViewArray<NoView>&, ViewArray<IntView>& y, Val c) {
319 assert(y.size() == 2);
320 return new (home) EqBin<Val,IntView,IntView>
321 (home,p,y[0],y[1],-c);
322 }
323 template<class Val>
324 forceinline Actor*
325 eqtobin(Space& home, Propagator& p,
326 ViewArray<IntView>& x, ViewArray<IntView>& y, Val c) {
327 if (x.size() == 2)
328 return new (home) EqBin<Val,IntView,IntView>
329 (home,p,x[0],x[1],c);
330 if (x.size() == 1)
331 return new (home) EqBin<Val,IntView,MinusView>
332 (home,p,x[0],MinusView(y[0]),c);
333 return new (home) EqBin<Val,IntView,IntView>
334 (home,p,y[0],y[1],-c);
335 }
336
337 /**
338 * \brief Rewriting of equality to ternary propagators
339 *
340 */
341 template<class Val, class P, class N>
342 forceinline Actor*
343 eqtoter(Space&, Propagator&, ViewArray<P>&, ViewArray<N>&, Val) {
344 return nullptr;
345 }
346 template<class Val>
347 forceinline Actor*
348 eqtoter(Space& home, Propagator& p,
349 ViewArray<IntView>& x, ViewArray<NoView>&, Val c) {
350 assert(x.size() == 3);
351 return new (home) EqTer<Val,IntView,IntView,IntView>
352 (home,p,x[0],x[1],x[2],c);
353 }
354 template<class Val>
355 forceinline Actor*
356 eqtoter(Space& home, Propagator& p,
357 ViewArray<NoView>&, ViewArray<IntView>& y, Val c) {
358 assert(y.size() == 3);
359 return new (home) EqTer<Val,IntView,IntView,IntView>
360 (home,p,y[0],y[1],y[2],-c);
361 }
362 template<class Val>
363 forceinline Actor*
364 eqtoter(Space& home, Propagator& p,
365 ViewArray<IntView>& x, ViewArray<IntView>& y, Val c) {
366 if (x.size() == 3)
367 return new (home) EqTer<Val,IntView,IntView,IntView>
368 (home,p,x[0],x[1],x[2],c);
369 if (x.size() == 2)
370 return new (home) EqTer<Val,IntView,IntView,MinusView>
371 (home,p,x[0],x[1],MinusView(y[0]),c);
372 if (x.size() == 1)
373 return new (home) EqTer<Val,IntView,IntView,MinusView>
374 (home,p,y[0],y[1],MinusView(x[0]),-c);
375 return new (home) EqTer<Val,IntView,IntView,IntView>
376 (home,p,y[0],y[1],y[2],-c);
377 }
378
379 template<class Val, class P, class N>
380 Actor*
381 Eq<Val,P,N>::copy(Space& home) {
382 if (isunit(x,y)) {
383 // Check whether rewriting is possible
384 if (x.size() + y.size() == 2)
385 return eqtobin(home,*this,x,y,c);
386 if (x.size() + y.size() == 3)
387 return eqtoter(home,*this,x,y,c);
388 }
389 return new (home) Eq<Val,P,N>(home,*this);
390 }
391
392 template<class Val, class P, class N>
393 ExecStatus
394 Eq<Val,P,N>::propagate(Space& home, const ModEventDelta& med) {
395 return prop_bnd<Val,P,N>(home,med,*this,x,y,c);
396 }
397
398 /*
399 * Reified bound consistent linear equation
400 *
401 */
402
403 template<class Val, class P, class N, class Ctrl, ReifyMode rm>
404 forceinline
405 ReEq<Val,P,N,Ctrl,rm>::ReEq(Home home,
406 ViewArray<P>& x, ViewArray<N>& y, Val c, Ctrl b)
407 : ReLin<Val,P,N,PC_INT_BND,Ctrl>(home,x,y,c,b) {}
408
409 template<class Val, class P, class N, class Ctrl, ReifyMode rm>
410 ExecStatus
411 ReEq<Val,P,N,Ctrl,rm>::post(Home home,
412 ViewArray<P>& x, ViewArray<N>& y, Val c, Ctrl b) {
413 ViewArray<NoView> nva;
414 if (y.size() == 0) {
415 (void) new (home) ReEq<Val,P,NoView,Ctrl,rm>(home,x,nva,c,b);
416 } else if (x.size() == 0) {
417 (void) new (home) ReEq<Val,N,NoView,Ctrl,rm>(home,y,nva,-c,b);
418 } else {
419 (void) new (home) ReEq<Val,P,N,Ctrl,rm>(home,x,y,c,b);
420 }
421 return ES_OK;
422 }
423
424
425 template<class Val, class P, class N, class Ctrl, ReifyMode rm>
426 forceinline
427 ReEq<Val,P,N,Ctrl,rm>::ReEq(Space& home, ReEq<Val,P,N,Ctrl,rm>& p)
428 : ReLin<Val,P,N,PC_INT_BND,Ctrl>(home,p) {}
429
430 template<class Val, class P, class N, class Ctrl, ReifyMode rm>
431 Actor*
432 ReEq<Val,P,N,Ctrl,rm>::copy(Space& home) {
433 return new (home) ReEq<Val,P,N,Ctrl,rm>(home,*this);
434 }
435
436 template<class Val, class P, class N, class Ctrl, ReifyMode rm>
437 ExecStatus
438 ReEq<Val,P,N,Ctrl,rm>::propagate(Space& home, const ModEventDelta& med) {
439 if (b.zero()) {
440 if (rm == RM_IMP)
441 return home.ES_SUBSUMED(*this);
442 GECODE_REWRITE(*this,(Nq<Val,P,N>::post(home(*this),x,y,c)));
443 }
444 if (b.one()) {
445 if (rm == RM_PMI)
446 return home.ES_SUBSUMED(*this);
447 GECODE_REWRITE(*this,(Eq<Val,P,N>::post(home(*this),x,y,c)));
448 }
449
450 Val sl = 0;
451 Val su = 0;
452
453 bounds_p<Val,P>(med, x, c, sl, su);
454 bounds_n<Val,N>(med, y, c, sl, su);
455
456 if ((-sl == c) && (-su == c)) {
457 if (rm != RM_IMP)
458 GECODE_ME_CHECK(b.one_none(home));
459 return home.ES_SUBSUMED(*this);
460 }
461 if ((-sl > c) || (-su < c)) {
462 if (rm != RM_PMI)
463 GECODE_ME_CHECK(b.zero_none(home));
464 return home.ES_SUBSUMED(*this);
465 }
466 return ES_FIX;
467 }
468
469
470 /*
471 * Domain consistent linear disequation
472 *
473 */
474
475 template<class Val, class P, class N>
476 forceinline
477 Nq<Val,P,N>::Nq(Home home, ViewArray<P>& x, ViewArray<N>& y, Val c)
478 : Lin<Val,P,N,PC_INT_VAL>(home,x,y,c) {}
479
480 template<class Val, class P, class N>
481 ExecStatus
482 Nq<Val,P,N>::post(Home home, ViewArray<P>& x, ViewArray<N>& y, Val c) {
483 ViewArray<NoView> nva;
484 if (y.size() == 0) {
485 (void) new (home) Nq<Val,P,NoView>(home,x,nva,c);
486 } else if (x.size() == 0) {
487 (void) new (home) Nq<Val,N,NoView>(home,y,nva,-c);
488 } else {
489 (void) new (home) Nq<Val,P,N>(home,x,y,c);
490 }
491 return ES_OK;
492 }
493
494
495 template<class Val, class P, class N>
496 forceinline
497 Nq<Val,P,N>::Nq(Space& home, Nq<Val,P,N>& p)
498 : Lin<Val,P,N,PC_INT_VAL>(home,p) {}
499
500 /**
501 * \brief Rewriting of disequality to binary propagators
502 *
503 */
504 template<class Val, class P, class N>
505 forceinline Actor*
506 nqtobin(Space&, Propagator&, ViewArray<P>&, ViewArray<N>&, Val) {
507 return nullptr;
508 }
509 template<class Val>
510 forceinline Actor*
511 nqtobin(Space& home, Propagator& p,
512 ViewArray<IntView>& x, ViewArray<NoView>&, Val c) {
513 assert(x.size() == 2);
514 return new (home) NqBin<Val,IntView,IntView>
515 (home,p,x[0],x[1],c);
516 }
517 template<class Val>
518 forceinline Actor*
519 nqtobin(Space& home, Propagator& p,
520 ViewArray<NoView>&, ViewArray<IntView>& y, Val c) {
521 assert(y.size() == 2);
522 return new (home) NqBin<Val,IntView,IntView>
523 (home,p,y[0],y[1],-c);
524 }
525 template<class Val>
526 forceinline Actor*
527 nqtobin(Space& home, Propagator& p,
528 ViewArray<IntView>& x, ViewArray<IntView>& y, Val c) {
529 if (x.size() == 2)
530 return new (home) NqBin<Val,IntView,IntView>
531 (home,p,x[0],x[1],c);
532 if (x.size() == 1)
533 return new (home) NqBin<Val,IntView,MinusView>
534 (home,p,x[0],MinusView(y[0]),c);
535 return new (home) NqBin<Val,IntView,IntView>
536 (home,p,y[0],y[1],-c);
537 }
538
539 /**
540 * \brief Rewriting of disequality to ternary propagators
541 *
542 */
543 template<class Val, class P, class N>
544 forceinline Actor*
545 nqtoter(Space&, Propagator&,ViewArray<P>&, ViewArray<N>&, Val) {
546 return nullptr;
547 }
548 template<class Val>
549 forceinline Actor*
550 nqtoter(Space& home, Propagator& p,
551 ViewArray<IntView>& x, ViewArray<NoView>&, Val c) {
552 assert(x.size() == 3);
553 return new (home) NqTer<Val,IntView,IntView,IntView>
554 (home,p,x[0],x[1],x[2],c);
555 }
556 template<class Val>
557 forceinline Actor*
558 nqtoter(Space& home, Propagator& p,
559 ViewArray<NoView>&, ViewArray<IntView>& y, Val c) {
560 assert(y.size() == 3);
561 return new (home) NqTer<Val,IntView,IntView,IntView>
562 (home,p,y[0],y[1],y[2],-c);
563 }
564 template<class Val>
565 forceinline Actor*
566 nqtoter(Space& home, Propagator& p,
567 ViewArray<IntView>& x, ViewArray<IntView>& y, Val c) {
568 if (x.size() == 3)
569 return new (home) NqTer<Val,IntView,IntView,IntView>
570 (home,p,x[0],x[1],x[2],c);
571 if (x.size() == 2)
572 return new (home) NqTer<Val,IntView,IntView,MinusView>
573 (home,p,x[0],x[1],MinusView(y[0]),c);
574 if (x.size() == 1)
575 return new (home) NqTer<Val,IntView,IntView,MinusView>
576 (home,p,y[0],y[1],MinusView(x[0]),-c);
577 return new (home) NqTer<Val,IntView,IntView,IntView>
578 (home,p,y[0],y[1],y[2],-c);
579 }
580
581 template<class Val, class P, class N>
582 Actor*
583 Nq<Val,P,N>::copy(Space& home) {
584 if (isunit(x,y)) {
585 // Check whether rewriting is possible
586 if (x.size() + y.size() == 2)
587 return nqtobin(home,*this,x,y,c);
588 if (x.size() + y.size() == 3)
589 return nqtoter(home,*this,x,y,c);
590 }
591 return new (home) Nq<Val,P,N>(home,*this);
592 }
593
594 template<class Val, class P, class N>
595 ExecStatus
596 Nq<Val,P,N>::propagate(Space& home, const ModEventDelta&) {
597 for (int i=x.size(); i--; )
598 if (x[i].assigned()) {
599 c -= x[i].val(); x.move_lst(i);
600 }
601 for (int i=y.size(); i--; )
602 if (y[i].assigned()) {
603 c += y[i].val(); y.move_lst(i);
604 }
605 if (x.size() + y.size() <= 1) {
606 if (x.size() == 1) {
607 GECODE_ME_CHECK(x[0].nq(home,c)); return home.ES_SUBSUMED(*this);
608 }
609 if (y.size() == 1) {
610 GECODE_ME_CHECK(y[0].nq(home,-c)); return home.ES_SUBSUMED(*this);
611 }
612 return (c == static_cast<Val>(0)) ?
613 ES_FAILED : home.ES_SUBSUMED(*this);
614 }
615 return ES_FIX;
616 }
617
618
619 /*
620 * Bound consistent linear inequation
621 *
622 */
623
624 template<class Val, class P, class N>
625 forceinline
626 Lq<Val,P,N>::Lq(Home home, ViewArray<P>& x, ViewArray<N>& y, Val c)
627 : Lin<Val,P,N,PC_INT_BND>(home,x,y,c) {}
628
629 template<class Val, class P, class N>
630 ExecStatus
631 Lq<Val,P,N>::post(Home home, ViewArray<P>& x, ViewArray<N>& y, Val c) {
632 ViewArray<NoView> nva;
633 if (y.size() == 0) {
634 (void) new (home) Lq<Val,P,NoView>(home,x,nva,c);
635 } else if (x.size() == 0) {
636 (void) new (home) Lq<Val,NoView,N>(home,nva,y,c);
637 } else {
638 (void) new (home) Lq<Val,P,N>(home,x,y,c);
639 }
640 return ES_OK;
641 }
642
643
644 template<class Val, class P, class N>
645 forceinline
646 Lq<Val,P,N>::Lq(Space& home, Lq<Val,P,N>& p)
647 : Lin<Val,P,N,PC_INT_BND>(home,p) {}
648
649 /**
650 * \brief Rewriting of inequality to binary propagators
651 *
652 */
653 template<class Val, class P, class N>
654 forceinline Actor*
655 lqtobin(Space&, Propagator&,ViewArray<P>&, ViewArray<N>&, Val) {
656 return nullptr;
657 }
658 template<class Val>
659 forceinline Actor*
660 lqtobin(Space& home, Propagator& p,
661 ViewArray<IntView>& x, ViewArray<NoView>&, Val c) {
662 assert(x.size() == 2);
663 return new (home) LqBin<Val,IntView,IntView>
664 (home,p,x[0],x[1],c);
665 }
666 template<class Val>
667 forceinline Actor*
668 lqtobin(Space& home, Propagator& p,
669 ViewArray<NoView>&, ViewArray<IntView>& y, Val c) {
670 assert(y.size() == 2);
671 return new (home) LqBin<Val,MinusView,MinusView>
672 (home,p,MinusView(y[0]),MinusView(y[1]),c);
673 }
674 template<class Val>
675 forceinline Actor*
676 lqtobin(Space& home, Propagator& p,
677 ViewArray<IntView>& x, ViewArray<IntView>& y, Val c) {
678 if (x.size() == 2)
679 return new (home) LqBin<Val,IntView,IntView>
680 (home,p,x[0],x[1],c);
681 if (x.size() == 1)
682 return new (home) LqBin<Val,IntView,MinusView>
683 (home,p,x[0],MinusView(y[0]),c);
684 return new (home) LqBin<Val,MinusView,MinusView>
685 (home,p,MinusView(y[0]),MinusView(y[1]),c);
686 }
687
688 /**
689 * \brief Rewriting of inequality to ternary propagators
690 *
691 */
692 template<class Val, class P, class N>
693 forceinline Actor*
694 lqtoter(Space&, Propagator&, ViewArray<P>&, ViewArray<N>&, Val) {
695 return nullptr;
696 }
697 template<class Val>
698 forceinline Actor*
699 lqtoter(Space& home, Propagator& p,
700 ViewArray<IntView>& x, ViewArray<NoView>&, Val c) {
701 assert(x.size() == 3);
702 return new (home) LqTer<Val,IntView,IntView,IntView>
703 (home,p,x[0],x[1],x[2],c);
704 }
705 template<class Val>
706 forceinline Actor*
707 lqtoter(Space& home, Propagator& p,
708 ViewArray<NoView>&, ViewArray<IntView>& y, Val c) {
709 assert(y.size() == 3);
710 return new (home) LqTer<Val,MinusView,MinusView,MinusView>
711 (home,p,MinusView(y[0]),MinusView(y[1]),MinusView(y[2]),c);
712 }
713 template<class Val>
714 forceinline Actor*
715 lqtoter(Space& home, Propagator& p,
716 ViewArray<IntView>& x, ViewArray<IntView>& y, Val c) {
717 if (x.size() == 3)
718 return new (home) LqTer<Val,IntView,IntView,IntView>
719 (home,p,x[0],x[1],x[2],c);
720 if (x.size() == 2)
721 return new (home) LqTer<Val,IntView,IntView,MinusView>
722 (home,p,x[0],x[1],MinusView(y[0]),c);
723 if (x.size() == 1)
724 return new (home) LqTer<Val,IntView,MinusView,MinusView>
725 (home,p,x[0],MinusView(y[0]),MinusView(y[1]),c);
726 return new (home) LqTer<Val,MinusView,MinusView,MinusView>
727 (home,p,MinusView(y[0]),MinusView(y[1]),MinusView(y[2]),c);
728 }
729
730 template<class Val, class P, class N>
731 Actor*
732 Lq<Val,P,N>::copy(Space& home) {
733 if (isunit(x,y)) {
734 // Check whether rewriting is possible
735 if (x.size() + y.size() == 2)
736 return lqtobin(home,*this,x,y,c);
737 if (x.size() + y.size() == 3)
738 return lqtoter(home,*this,x,y,c);
739 }
740 return new (home) Lq<Val,P,N>(home,*this);
741 }
742
743 template<class Val, class P, class N>
744 ExecStatus
745 Lq<Val,P,N>::propagate(Space& home, const ModEventDelta& med) {
746 // Eliminate singletons
747 Val sl = 0;
748
749 if (IntView::me(med) == ME_INT_VAL) {
750 for (int i=x.size(); i--; ) {
751 Val m = x[i].min();
752 if (x[i].assigned()) {
753 c -= m; x.move_lst(i);
754 } else {
755 sl -= m;
756 }
757 }
758 for (int i=y.size(); i--; ) {
759 Val m = y[i].max();
760 if (y[i].assigned()) {
761 c += m; y.move_lst(i);
762 } else {
763 sl += m;
764 }
765 }
766 if ((x.size() + y.size()) <= 1) {
767 if (x.size() == 1) {
768 GECODE_ME_CHECK(x[0].lq(home,c));
769 return home.ES_SUBSUMED(*this);
770 }
771 if (y.size() == 1) {
772 GECODE_ME_CHECK(y[0].gq(home,-c));
773 return home.ES_SUBSUMED(*this);
774 }
775 return (c >= static_cast<Val>(0)) ?
776 home.ES_SUBSUMED(*this) : ES_FAILED;
777 }
778 } else {
779 for (int i=0; i<x.size(); i++)
780 sl -= x[i].min();
781 for (int i=0; i<y.size(); i++)
782 sl += y[i].max();
783 }
784
785 sl += c;
786
787 ExecStatus es = ES_FIX;
788 bool assigned = true;
789 for (int i=0; i<x.size(); i++) {
790 assert(!x[i].assigned());
791 Val slx = sl + x[i].min();
792 ModEvent me = x[i].lq(home,slx);
793 if (me == ME_INT_FAILED)
794 return ES_FAILED;
795 if (me != ME_INT_VAL)
796 assigned = false;
797 if (me_modified(me) && (slx != x[i].max()))
798 es = ES_NOFIX;
799 }
800
801 for (int i=0; i<y.size(); i++) {
802 assert(!y[i].assigned());
803 Val sly = y[i].max() - sl;
804 ModEvent me = y[i].gq(home,sly);
805 if (me == ME_INT_FAILED)
806 return ES_FAILED;
807 if (me != ME_INT_VAL)
808 assigned = false;
809 if (me_modified(me) && (sly != y[i].min()))
810 es = ES_NOFIX;
811 }
812 return assigned ? home.ES_SUBSUMED(*this) : es;
813 }
814
815 /*
816 * Reified bound consistent linear inequation
817 *
818 */
819
820 template<class Val, class P, class N, ReifyMode rm>
821 forceinline
822 ReLq<Val,P,N,rm>::ReLq(Home home,
823 ViewArray<P>& x, ViewArray<N>& y, Val c, BoolView b)
824 : ReLin<Val,P,N,PC_INT_BND,BoolView>(home,x,y,c,b) {}
825
826 template<class Val, class P, class N, ReifyMode rm>
827 ExecStatus
828 ReLq<Val,P,N,rm>::post(Home home,
829 ViewArray<P>& x, ViewArray<N>& y, Val c, BoolView b) {
830 ViewArray<NoView> nva;
831 if (y.size() == 0) {
832 (void) new (home) ReLq<Val,P,NoView,rm>(home,x,nva,c,b);
833 } else if (x.size() == 0) {
834 (void) new (home) ReLq<Val,NoView,N,rm>(home,nva,y,c,b);
835 } else {
836 (void) new (home) ReLq<Val,P,N,rm>(home,x,y,c,b);
837 }
838 return ES_OK;
839 }
840
841
842 template<class Val, class P, class N, ReifyMode rm>
843 forceinline
844 ReLq<Val,P,N,rm>::ReLq(Space& home, ReLq<Val,P,N,rm>& p)
845 : ReLin<Val,P,N,PC_INT_BND,BoolView>(home,p) {}
846
847 template<class Val, class P, class N, ReifyMode rm>
848 Actor*
849 ReLq<Val,P,N,rm>::copy(Space& home) {
850 return new (home) ReLq<Val,P,N,rm>(home,*this);
851 }
852
853 template<class Val, class P, class N, ReifyMode rm>
854 ExecStatus
855 ReLq<Val,P,N,rm>::propagate(Space& home, const ModEventDelta& med) {
856 if (b.zero()) {
857 if (rm == RM_IMP)
858 return home.ES_SUBSUMED(*this);
859 GECODE_REWRITE(*this,(Lq<Val,N,P>::post(home(*this),y,x,-c-1)));
860 }
861 if (b.one()) {
862 if (rm == RM_PMI)
863 return home.ES_SUBSUMED(*this);
864 GECODE_REWRITE(*this,(Lq<Val,P,N>::post(home(*this),x,y,c)));
865 }
866
867 // Eliminate singletons
868 Val sl = 0;
869 Val su = 0;
870
871 bounds_p<Val,P>(med,x,c,sl,su);
872 bounds_n<Val,N>(med,y,c,sl,su);
873
874 if (-sl > c) {
875 if (rm != RM_PMI)
876 GECODE_ME_CHECK(b.zero_none(home));
877 return home.ES_SUBSUMED(*this);
878 }
879 if (-su <= c) {
880 if (rm != RM_IMP)
881 GECODE_ME_CHECK(b.one_none(home));
882 return home.ES_SUBSUMED(*this);
883 }
884
885 return ES_FIX;
886 }
887
888}}}
889
890// STATISTICS: int-prop
891