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 * Tias Guns <tias.guns@cs.kuleuven.be>
6 *
7 * Copyright:
8 * Christian Schulte, 2002
9 * Tias Guns, 2009
10 *
11 * This file is part of Gecode, the generic constraint
12 * development environment:
13 * http://www.gecode.org
14 *
15 * Permission is hereby granted, free of charge, to any person obtaining
16 * a copy of this software and associated documentation files (the
17 * "Software"), to deal in the Software without restriction, including
18 * without limitation the rights to use, copy, modify, merge, publish,
19 * distribute, sublicense, and/or sell copies of the Software, and to
20 * permit persons to whom the Software is furnished to do so, subject to
21 * the following conditions:
22 *
23 * The above copyright notice and this permission notice shall be
24 * included in all copies or substantial portions of the Software.
25 *
26 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
30 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
31 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
32 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 *
34 */
35
36#include <gecode/int/linear.hh>
37#include <gecode/int/div.hh>
38
39namespace Gecode { namespace Int { namespace Linear {
40
41 /// Eliminate assigned views
42 forceinline void
43 eliminate(Term<BoolView>* t, int &n, long long int& d) {
44 for (int i=n; i--; )
45 if (t[i].x.one()) {
46 d -= t[i].a; t[i]=t[--n];
47 } else if (t[i].x.zero()) {
48 t[i]=t[--n];
49 }
50 Limits::check(d,"Int::linear");
51 }
52
53 /// Rewrite non-strict relations
54 forceinline void
55 rewrite(IntRelType &r, long long int &d) {
56 switch (r) {
57 case IRT_EQ: case IRT_NQ: case IRT_LQ: case IRT_GQ:
58 break;
59 case IRT_LE:
60 d--; r = IRT_LQ; break;
61 case IRT_GR:
62 d++; r = IRT_GQ; break;
63 default:
64 throw UnknownRelation("Int::linear");
65 }
66 }
67
68 forceinline void
69 post_pos_unit(Home home,
70 Term<BoolView>* t_p, int n_p,
71 IntRelType irt, IntView y, int c) {
72 switch (irt) {
73 case IRT_EQ:
74 {
75 ViewArray<BoolView> x(home,n_p);
76 for (int i=0; i<n_p; i++)
77 x[i]=t_p[i].x;
78 GECODE_ES_FAIL((EqBoolView<BoolView,IntView>
79 ::post(home,x,y,c)));
80 }
81 break;
82 case IRT_NQ:
83 {
84 ViewArray<BoolView> x(home,n_p);
85 for (int i=0; i<n_p; i++)
86 x[i]=t_p[i].x;
87 GECODE_ES_FAIL((NqBoolView<BoolView,IntView>
88 ::post(home,x,y,c)));
89 }
90 break;
91 case IRT_GQ:
92 {
93 ViewArray<BoolView> x(home,n_p);
94 for (int i=0; i<n_p; i++)
95 x[i]=t_p[i].x;
96 GECODE_ES_FAIL((GqBoolView<BoolView,IntView>
97 ::post(home,x,y,c)));
98 }
99 break;
100 case IRT_LQ:
101 {
102 ViewArray<NegBoolView> x(home,n_p);
103 for (int i=0; i<n_p; i++)
104 x[i]=NegBoolView(t_p[i].x);
105 MinusView z(y);
106 GECODE_ES_FAIL((GqBoolView<NegBoolView,MinusView>
107 ::post(home,x,z,n_p-c)));
108 }
109 break;
110 default: GECODE_NEVER;
111 }
112 }
113
114 forceinline void
115 post_pos_unit(Home home,
116 Term<BoolView>* t_p, int n_p,
117 IntRelType irt, ZeroIntView, int c) {
118 switch (irt) {
119 case IRT_EQ:
120 {
121 ViewArray<BoolView> x(home,n_p);
122 for (int i=0; i<n_p; i++)
123 x[i]=t_p[i].x;
124 GECODE_ES_FAIL((EqBoolInt<BoolView>::post(home,x,c)));
125 }
126 break;
127 case IRT_NQ:
128 {
129 ViewArray<BoolView> x(home,n_p);
130 for (int i=0; i<n_p; i++)
131 x[i]=t_p[i].x;
132 GECODE_ES_FAIL((NqBoolInt<BoolView>::post(home,x,c)));
133 }
134 break;
135 case IRT_GQ:
136 {
137 ViewArray<BoolView> x(home,n_p);
138 for (int i=0; i<n_p; i++)
139 x[i]=t_p[i].x;
140 GECODE_ES_FAIL((GqBoolInt<BoolView>::post(home,x,c)));
141 }
142 break;
143 case IRT_LQ:
144 {
145 ViewArray<NegBoolView> x(home,n_p);
146 for (int i=0; i<n_p; i++)
147 x[i]=NegBoolView(t_p[i].x);
148 GECODE_ES_FAIL((GqBoolInt<NegBoolView>::post(home,x,n_p-c)));
149 }
150 break;
151 default: GECODE_NEVER;
152 }
153 }
154
155 forceinline void
156 post_pos_unit(Home home,
157 Term<BoolView>* t_p, int n_p,
158 IntRelType irt, int c, Reify r,
159 IntPropLevel) {
160 switch (irt) {
161 case IRT_EQ:
162 {
163 ViewArray<BoolView> x(home,n_p);
164 for (int i=0; i<n_p; i++)
165 x[i]=t_p[i].x;
166 switch (r.mode()) {
167 case RM_EQV:
168 GECODE_ES_FAIL((ReEqBoolInt<BoolView,BoolView,RM_EQV>::
169 post(home,x,c,r.var())));
170 break;
171 case RM_IMP:
172 GECODE_ES_FAIL((ReEqBoolInt<BoolView,BoolView,RM_IMP>::
173 post(home,x,c,r.var())));
174 break;
175 case RM_PMI:
176 GECODE_ES_FAIL((ReEqBoolInt<BoolView,BoolView,RM_PMI>::
177 post(home,x,c,r.var())));
178 break;
179 default: GECODE_NEVER;
180 }
181 }
182 break;
183 case IRT_NQ:
184 {
185 ViewArray<BoolView> x(home,n_p);
186 for (int i=0; i<n_p; i++)
187 x[i]=t_p[i].x;
188 NegBoolView nb(r.var());
189 switch (r.mode()) {
190 case RM_EQV:
191 GECODE_ES_FAIL((ReEqBoolInt<BoolView,NegBoolView,RM_EQV>::
192 post(home,x,c,nb)));
193 break;
194 case RM_IMP:
195 GECODE_ES_FAIL((ReEqBoolInt<BoolView,NegBoolView,RM_PMI>::
196 post(home,x,c,nb)));
197 break;
198 case RM_PMI:
199 GECODE_ES_FAIL((ReEqBoolInt<BoolView,NegBoolView,RM_IMP>::
200 post(home,x,c,nb)));
201 break;
202 default: GECODE_NEVER;
203 }
204 }
205 break;
206 case IRT_GQ:
207 {
208 ViewArray<BoolView> x(home,n_p);
209 for (int i=0; i<n_p; i++)
210 x[i]=t_p[i].x;
211 switch (r.mode()) {
212 case RM_EQV:
213 GECODE_ES_FAIL((ReGqBoolInt<BoolView,BoolView,RM_EQV>::
214 post(home,x,c,r.var())));
215 break;
216 case RM_IMP:
217 GECODE_ES_FAIL((ReGqBoolInt<BoolView,BoolView,RM_IMP>::
218 post(home,x,c,r.var())));
219 break;
220 case RM_PMI:
221 GECODE_ES_FAIL((ReGqBoolInt<BoolView,BoolView,RM_PMI>::
222 post(home,x,c,r.var())));
223 break;
224 default: GECODE_NEVER;
225 }
226 }
227 break;
228 case IRT_LQ:
229 {
230 ViewArray<NegBoolView> x(home,n_p);
231 for (int i=0; i<n_p; i++)
232 x[i]=NegBoolView(t_p[i].x);
233 switch (r.mode()) {
234 case RM_EQV:
235 GECODE_ES_FAIL((ReGqBoolInt<NegBoolView,BoolView,RM_EQV>::
236 post(home,x,n_p-c,r.var())));
237 break;
238 case RM_IMP:
239 GECODE_ES_FAIL((ReGqBoolInt<NegBoolView,BoolView,RM_IMP>::
240 post(home,x,n_p-c,r.var())));
241 break;
242 case RM_PMI:
243 GECODE_ES_FAIL((ReGqBoolInt<NegBoolView,BoolView,RM_PMI>::
244 post(home,x,n_p-c,r.var())));
245 break;
246 default: GECODE_NEVER;
247 }
248 }
249 break;
250 default: GECODE_NEVER;
251 }
252 }
253
254 forceinline void
255 post_neg_unit(Home home,
256 Term<BoolView>* t_n, int n_n,
257 IntRelType irt, IntView y, int c) {
258 switch (irt) {
259 case IRT_EQ:
260 {
261 ViewArray<BoolView> x(home,n_n);
262 for (int i=0; i<n_n; i++)
263 x[i]=t_n[i].x;
264 MinusView z(y);
265 GECODE_ES_FAIL((EqBoolView<BoolView,MinusView>
266 ::post(home,x,z,-c)));
267 }
268 break;
269 case IRT_NQ:
270 {
271 ViewArray<BoolView> x(home,n_n);
272 for (int i=0; i<n_n; i++)
273 x[i]=t_n[i].x;
274 MinusView z(y);
275 GECODE_ES_FAIL((NqBoolView<BoolView,MinusView>
276 ::post(home,x,z,-c)));
277 }
278 break;
279 case IRT_GQ:
280 {
281 ViewArray<NegBoolView> x(home,n_n);
282 for (int i=0; i<n_n; i++)
283 x[i]=NegBoolView(t_n[i].x);
284 GECODE_ES_FAIL((GqBoolView<NegBoolView,IntView>
285 ::post(home,x,y,n_n+c)));
286 }
287 break;
288 case IRT_LQ:
289 {
290 ViewArray<BoolView> x(home,n_n);
291 for (int i=0; i<n_n; i++)
292 x[i]=t_n[i].x;
293 MinusView z(y);
294 GECODE_ES_FAIL((GqBoolView<BoolView,MinusView>
295 ::post(home,x,z,-c)));
296 }
297 break;
298 default: GECODE_NEVER;
299 }
300 }
301
302 forceinline void
303 post_neg_unit(Home home,
304 Term<BoolView>* t_n, int n_n,
305 IntRelType irt, ZeroIntView, int c) {
306 switch (irt) {
307 case IRT_EQ:
308 {
309 ViewArray<BoolView> x(home,n_n);
310 for (int i=0; i<n_n; i++)
311 x[i]=t_n[i].x;
312 GECODE_ES_FAIL((EqBoolInt<BoolView>::post(home,x,-c)));
313 }
314 break;
315 case IRT_NQ:
316 {
317 ViewArray<BoolView> x(home,n_n);
318 for (int i=0; i<n_n; i++)
319 x[i]=t_n[i].x;
320 GECODE_ES_FAIL((NqBoolInt<BoolView>::post(home,x,-c)));
321 }
322 break;
323 case IRT_GQ:
324 {
325 ViewArray<NegBoolView> x(home,n_n);
326 for (int i=0; i<n_n; i++)
327 x[i]=NegBoolView(t_n[i].x);
328 GECODE_ES_FAIL((GqBoolInt<NegBoolView>::post(home,x,n_n+c)));
329 }
330 break;
331 case IRT_LQ:
332 {
333 ViewArray<BoolView> x(home,n_n);
334 for (int i=0; i<n_n; i++)
335 x[i]=t_n[i].x;
336 GECODE_ES_FAIL((GqBoolInt<BoolView>::post(home,x,-c)));
337 }
338 break;
339 default: GECODE_NEVER;
340 }
341 }
342
343 forceinline void
344 post_neg_unit(Home home,
345 Term<BoolView>* t_n, int n_n,
346 IntRelType irt, int c, Reify r,
347 IntPropLevel) {
348 switch (irt) {
349 case IRT_EQ:
350 {
351 ViewArray<BoolView> x(home,n_n);
352 for (int i=0; i<n_n; i++)
353 x[i]=t_n[i].x;
354 switch (r.mode()) {
355 case RM_EQV:
356 GECODE_ES_FAIL((ReEqBoolInt<BoolView,BoolView,RM_EQV>::
357 post(home,x,-c,r.var())));
358 break;
359 case RM_IMP:
360 GECODE_ES_FAIL((ReEqBoolInt<BoolView,BoolView,RM_IMP>::
361 post(home,x,-c,r.var())));
362 break;
363 case RM_PMI:
364 GECODE_ES_FAIL((ReEqBoolInt<BoolView,BoolView,RM_PMI>::
365 post(home,x,-c,r.var())));
366 break;
367 default: GECODE_NEVER;
368 }
369 }
370 break;
371 case IRT_NQ:
372 {
373 ViewArray<BoolView> x(home,n_n);
374 for (int i=0; i<n_n; i++)
375 x[i]=t_n[i].x;
376 NegBoolView nb(r.var());
377 switch (r.mode()) {
378 case RM_EQV:
379 GECODE_ES_FAIL((ReEqBoolInt<BoolView,NegBoolView,RM_EQV>::
380 post(home,x,-c,nb)));
381 break;
382 case RM_IMP:
383 GECODE_ES_FAIL((ReEqBoolInt<BoolView,NegBoolView,RM_PMI>::
384 post(home,x,-c,nb)));
385 break;
386 case RM_PMI:
387 GECODE_ES_FAIL((ReEqBoolInt<BoolView,NegBoolView,RM_IMP>::
388 post(home,x,-c,nb)));
389 break;
390 default: GECODE_NEVER;
391 }
392 }
393 break;
394 case IRT_GQ:
395 {
396 ViewArray<NegBoolView> x(home,n_n);
397 for (int i=0; i<n_n; i++)
398 x[i]=NegBoolView(t_n[i].x);
399 switch (r.mode()) {
400 case RM_EQV:
401 GECODE_ES_FAIL((ReGqBoolInt<NegBoolView,BoolView,RM_EQV>::
402 post(home,x,n_n+c,r.var())));
403 break;
404 case RM_IMP:
405 GECODE_ES_FAIL((ReGqBoolInt<NegBoolView,BoolView,RM_IMP>::
406 post(home,x,n_n+c,r.var())));
407 break;
408 case RM_PMI:
409 GECODE_ES_FAIL((ReGqBoolInt<NegBoolView,BoolView,RM_PMI>::
410 post(home,x,n_n+c,r.var())));
411 break;
412 default: GECODE_NEVER;
413 }
414 }
415 break;
416 case IRT_LQ:
417 {
418 ViewArray<BoolView> x(home,n_n);
419 for (int i=0; i<n_n; i++)
420 x[i]=t_n[i].x;
421 switch (r.mode()) {
422 case RM_EQV:
423 GECODE_ES_FAIL((ReGqBoolInt<BoolView,BoolView,RM_EQV>::
424 post(home,x,-c,r.var())));
425 break;
426 case RM_IMP:
427 GECODE_ES_FAIL((ReGqBoolInt<BoolView,BoolView,RM_IMP>::
428 post(home,x,-c,r.var())));
429 break;
430 case RM_PMI:
431 GECODE_ES_FAIL((ReGqBoolInt<BoolView,BoolView,RM_PMI>::
432 post(home,x,-c,r.var())));
433 break;
434 default: GECODE_NEVER;
435 }
436 }
437 break;
438 default: GECODE_NEVER;
439 }
440 }
441
442 forceinline void
443 post_mixed(Home home,
444 Term<BoolView>* t_p, int n_p,
445 Term<BoolView>* t_n, int n_n,
446 IntRelType irt, IntView y, int c) {
447 ScaleBoolArray b_p(home,n_p);
448 {
449 ScaleBool* f=b_p.fst();
450 for (int i=0; i<n_p; i++) {
451 f[i].x=t_p[i].x; f[i].a=t_p[i].a;
452 }
453 }
454 ScaleBoolArray b_n(home,n_n);
455 {
456 ScaleBool* f=b_n.fst();
457 for (int i=0; i<n_n; i++) {
458 f[i].x=t_n[i].x; f[i].a=t_n[i].a;
459 }
460 }
461 switch (irt) {
462 case IRT_EQ:
463 GECODE_ES_FAIL((EqBoolScale<ScaleBoolArray,ScaleBoolArray,IntView>
464 ::post(home,b_p,b_n,y,c)));
465 break;
466 case IRT_NQ:
467 GECODE_ES_FAIL((NqBoolScale<ScaleBoolArray,ScaleBoolArray,IntView>
468 ::post(home,b_p,b_n,y,c)));
469 break;
470 case IRT_LQ:
471 GECODE_ES_FAIL((LqBoolScale<ScaleBoolArray,ScaleBoolArray,IntView>
472 ::post(home,b_p,b_n,y,c)));
473 break;
474 case IRT_GQ:
475 {
476 MinusView m(y);
477 GECODE_ES_FAIL((LqBoolScale<ScaleBoolArray,ScaleBoolArray,MinusView>
478 ::post(home,b_n,b_p,m,-c)));
479 }
480 break;
481 default:
482 GECODE_NEVER;
483 }
484 }
485
486
487 forceinline void
488 post_mixed(Home home,
489 Term<BoolView>* t_p, int n_p,
490 Term<BoolView>* t_n, int n_n,
491 IntRelType irt, ZeroIntView y, int c) {
492 ScaleBoolArray b_p(home,n_p);
493 {
494 ScaleBool* f=b_p.fst();
495 for (int i=0; i<n_p; i++) {
496 f[i].x=t_p[i].x; f[i].a=t_p[i].a;
497 }
498 }
499 ScaleBoolArray b_n(home,n_n);
500 {
501 ScaleBool* f=b_n.fst();
502 for (int i=0; i<n_n; i++) {
503 f[i].x=t_n[i].x; f[i].a=t_n[i].a;
504 }
505 }
506 switch (irt) {
507 case IRT_EQ:
508 GECODE_ES_FAIL(
509 (EqBoolScale<ScaleBoolArray,ScaleBoolArray,ZeroIntView>
510 ::post(home,b_p,b_n,y,c)));
511 break;
512 case IRT_NQ:
513 GECODE_ES_FAIL(
514 (NqBoolScale<ScaleBoolArray,ScaleBoolArray,ZeroIntView>
515 ::post(home,b_p,b_n,y,c)));
516 break;
517 case IRT_LQ:
518 GECODE_ES_FAIL(
519 (LqBoolScale<ScaleBoolArray,ScaleBoolArray,ZeroIntView>
520 ::post(home,b_p,b_n,y,c)));
521 break;
522 case IRT_GQ:
523 GECODE_ES_FAIL(
524 (LqBoolScale<ScaleBoolArray,ScaleBoolArray,ZeroIntView>
525 ::post(home,b_n,b_p,y,-c)));
526 break;
527 default:
528 GECODE_NEVER;
529 }
530 }
531
532 template<class View>
533 forceinline void
534 post_all(Home home,
535 Term<BoolView>* t, int n,
536 IntRelType irt, View x, int c) {
537
538 Limits::check(c,"Int::linear");
539
540 long long int d = c;
541
542 eliminate(t,n,d);
543
544 Term<BoolView> *t_p, *t_n;
545 int n_p, n_n, gcd=0;
546 bool unit = normalize<BoolView>(t,n,t_p,n_p,t_n,n_n,gcd);
547
548 rewrite(irt,d);
549
550 c = static_cast<int>(d);
551
552 if (n == 0) {
553 switch (irt) {
554 case IRT_EQ: GECODE_ME_FAIL(x.eq(home,-c)); break;
555 case IRT_NQ: GECODE_ME_FAIL(x.nq(home,-c)); break;
556 case IRT_GQ: GECODE_ME_FAIL(x.lq(home,-c)); break;
557 case IRT_LQ: GECODE_ME_FAIL(x.gq(home,-c)); break;
558 default: GECODE_NEVER;
559 }
560 return;
561 }
562
563 // Check for overflow
564 {
565 long long int sl = static_cast<long long int>(x.max())+c;
566 long long int su = static_cast<long long int>(x.min())+c;
567 for (int i=0; i<n_p; i++)
568 su -= t_p[i].a;
569 for (int i=0; i<n_n; i++)
570 sl += t_n[i].a;
571 Limits::check(sl,"Int::linear");
572 Limits::check(su,"Int::linear");
573 }
574
575 if (unit && (n_n == 0)) {
576 /// All coefficients are 1
577 post_pos_unit(home,t_p,n_p,irt,x,c);
578 } else if (unit && (n_p == 0)) {
579 // All coefficients are -1
580 post_neg_unit(home,t_n,n_n,irt,x,c);
581 } else {
582 // Mixed coefficients
583 post_mixed(home,t_p,n_p,t_n,n_n,irt,x,c);
584 }
585 }
586
587
588 void
589 post(Home home,
590 Term<BoolView>* t, int n, IntRelType irt, IntView x, int c,
591 IntPropLevel) {
592 post_all(home,t,n,irt,x,c);
593 }
594
595 void
596 post(Home home,
597 Term<BoolView>* t, int n, IntRelType irt, int c,
598 IntPropLevel) {
599 ZeroIntView x;
600 post_all(home,t,n,irt,x,c);
601 }
602
603 void
604 post(Home home,
605 Term<BoolView>* t, int n, IntRelType irt, IntView x, Reify r,
606 IntPropLevel ipl) {
607 int l, u;
608 estimate(t,n,0,l,u);
609 IntVar z(home,l,u); IntView zv(z);
610 post_all(home,t,n,IRT_EQ,zv,0);
611 rel(home,z,irt,x,r,ipl);
612 }
613
614 void
615 post(Home home,
616 Term<BoolView>* t, int n, IntRelType irt, int c, Reify r,
617 IntPropLevel ipl) {
618
619 if (r.var().one()) {
620 if (r.mode() != RM_PMI)
621 post(home,t,n,irt,c,ipl);
622 return;
623 }
624 if (r.var().zero()) {
625 if (r.mode() != RM_IMP)
626 post(home,t,n,neg(irt),c,ipl);
627 return;
628 }
629
630 Limits::check(c,"Int::linear");
631
632 long long int d = c;
633
634 eliminate(t,n,d);
635
636 Term<BoolView> *t_p, *t_n;
637 int n_p, n_n, gcd=1;
638 bool unit = normalize<BoolView>(t,n,t_p,n_p,t_n,n_n,gcd);
639
640 rewrite(irt,d);
641
642 // Divide by gcd
643 if (gcd > 1) {
644 switch (irt) {
645 case IRT_EQ:
646 if ((d % gcd) != 0) {
647 if (r.mode() != RM_PMI)
648 GECODE_ME_FAIL(BoolView(r.var()).zero(home));
649 return;
650 }
651 d /= gcd;
652 break;
653 case IRT_NQ:
654 if ((d % gcd) == 0) {
655 if (r.mode() != RM_IMP)
656 GECODE_ME_FAIL(BoolView(r.var()).one(home));
657 return;
658 }
659 d /= gcd;
660 break;
661 case IRT_LQ:
662 d = floor_div_xp(d,static_cast<long long int>(gcd));
663 break;
664 case IRT_GQ:
665 d = ceil_div_xp(d,static_cast<long long int>(gcd));
666 break;
667 default: GECODE_NEVER;
668 }
669 }
670
671 c = static_cast<int>(d);
672
673 if (n == 0) {
674 bool fail = false;
675 switch (irt) {
676 case IRT_EQ: fail = (0 != c); break;
677 case IRT_NQ: fail = (0 == c); break;
678 case IRT_GQ: fail = (0 < c); break;
679 case IRT_LQ: fail = (0 > c); break;
680 default: GECODE_NEVER;
681 }
682 if (fail) {
683 if (r.mode() != RM_PMI)
684 GECODE_ME_FAIL(BoolView(r.var()).zero(home));
685 } else {
686 if (r.mode() != RM_IMP)
687 GECODE_ME_FAIL(BoolView(r.var()).one(home));
688 }
689 return;
690 }
691
692 // Check for overflow
693 {
694 long long int sl = c;
695 long long int su = c;
696 for (int i=0; i<n_p; i++)
697 su -= t_p[i].a;
698 for (int i=0; i<n_n; i++)
699 sl += t_n[i].a;
700 Limits::check(sl,"Int::linear");
701 Limits::check(su,"Int::linear");
702 }
703
704 if (unit && (n_n == 0)) {
705 /// All coefficients are 1
706 post_pos_unit(home,t_p,n_p,irt,c,r,ipl);
707 } else if (unit && (n_p == 0)) {
708 // All coefficients are -1
709 post_neg_unit(home,t_n,n_n,irt,c,r,ipl);
710 } else {
711 // Mixed coefficients
712 /*
713 * Denormalize: Make all t_n coefficients negative again
714 * (t_p and t_n are shared in t)
715 */
716 for (int i=0; i<n_n; i++)
717 t_n[i].a = -t_n[i].a;
718
719 // Note: still slow implementation
720 int l, u;
721 estimate(t,n,0,l,u);
722 IntVar z(home,l,u); IntView zv(z);
723 post_all(home,t,n,IRT_EQ,zv,0);
724 rel(home,z,irt,c,r,ipl);
725 }
726 }
727
728}}}
729
730// STATISTICS: int-post
731