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, 2010
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/minimodel.hh>
35#include <gecode/int/linear.hh>
36
37namespace Gecode {
38
39 /// Nodes for linear expressions
40 class LinIntExpr::Node {
41 public:
42 /// Nodes are reference counted
43 unsigned int use;
44 /// Integer variables in tree
45 int n_int;
46 /// Boolean variables in tree
47 int n_bool;
48 /// Type of expression
49 NodeType t;
50 /// Subexpressions
51 Node *l, *r;
52 /// Sum of integer or Boolean variables, or non-linear expression
53 union {
54 /// Integer views and coefficients
55 Int::Linear::Term<Int::IntView>* ti;
56 /// Bool views and coefficients
57 Int::Linear::Term<Int::BoolView>* tb;
58 /// Non-linear expression
59 NonLinIntExpr* ne;
60 } sum;
61 /// Coefficient and offset
62 int a, c;
63 /// Integer variable (potentially)
64 IntVar x_int;
65 /// Boolean variable (potentially)
66 BoolVar x_bool;
67 /// Default constructor
68 Node(void);
69 /// Generate linear terms from expression
70 void fill(Home home, const IntPropLevels& ipls,
71 Int::Linear::Term<Int::IntView>*& ti,
72 Int::Linear::Term<Int::BoolView>*& tb,
73 long long int m, long long int& d) const;
74 /// Generate linear terms for expressions
75 int fill(Home home, const IntPropLevels& ipls,
76 Int::Linear::Term<Int::IntView>* ti,
77 Int::Linear::Term<Int::BoolView>* tb) const;
78 /// Decrement reference count and possibly free memory
79 bool decrement(void);
80 /// Destructor
81 ~Node(void);
82 /// Memory management
83 static void* operator new(size_t size);
84 /// Memory management
85 static void operator delete(void* p,size_t size);
86 };
87
88 /*
89 * Operations for nodes
90 *
91 */
92 forceinline
93 LinIntExpr::Node::Node(void) : use(1) {
94 }
95
96 forceinline
97 LinIntExpr::Node::~Node(void) {
98 switch (t) {
99 case NT_SUM_INT:
100 if (n_int > 0)
101 heap.free<Int::Linear::Term<Int::IntView> >(sum.ti,n_int);
102 break;
103 case NT_SUM_BOOL:
104 if (n_bool > 0)
105 heap.free<Int::Linear::Term<Int::BoolView> >(sum.tb,n_bool);
106 break;
107 case NT_NONLIN:
108 delete sum.ne;
109 break;
110 default: ;
111 }
112 }
113
114 forceinline void*
115 LinIntExpr::Node::operator new(size_t size) {
116 return heap.ralloc(size);
117 }
118
119 forceinline void
120 LinIntExpr::Node::operator delete(void* p, size_t) {
121 heap.rfree(p);
122 }
123 bool
124 LinIntExpr::Node::decrement(void) {
125 if (--use == 0) {
126 if ((l != nullptr) && l->decrement())
127 delete l;
128 if ((r != nullptr) && r->decrement())
129 delete r;
130 return true;
131 }
132 return false;
133 }
134
135 /*
136 * Operations for expressions
137 *
138 */
139
140 LinIntExpr::LinIntExpr(const LinIntExpr& e)
141 : n(e.n) {
142 n->use++;
143 }
144
145 int
146 LinIntExpr::Node::fill(Home home, const IntPropLevels& ipls,
147 Int::Linear::Term<Int::IntView>* ti,
148 Int::Linear::Term<Int::BoolView>* tb) const {
149 long long int d=0;
150 fill(home,ipls,ti,tb,1,d);
151 Int::Limits::check(d,"MiniModel::LinIntExpr");
152 return static_cast<int>(d);
153 }
154
155 void
156 LinIntExpr::post(Home home, IntRelType irt,
157 const IntPropLevels& ipls) const {
158 if (home.failed()) return;
159 Region r;
160 if (n->n_bool == 0) {
161 // Only integer variables
162 if (n->t==NT_ADD && n->l == nullptr && n->r->t==NT_NONLIN) {
163 n->r->sum.ne->post(home,irt,-n->c,ipls);
164 } else if (n->t==NT_SUB && n->r->t==NT_NONLIN && n->l==nullptr) {
165 switch (irt) {
166 case IRT_LQ: irt=IRT_GQ; break;
167 case IRT_LE: irt=IRT_GR; break;
168 case IRT_GQ: irt=IRT_LQ; break;
169 case IRT_GR: irt=IRT_LE; break;
170 default: break;
171 }
172 n->r->sum.ne->post(home,irt,n->c,ipls);
173 } else if (irt==IRT_EQ &&
174 n->t==NT_SUB && n->r->t==NT_NONLIN &&
175 n->l != nullptr && n->l->t==NT_VAR_INT
176 && n->l->a==1) {
177 (void) n->r->sum.ne->post(home,&n->l->x_int,ipls);
178 } else if (irt==IRT_EQ &&
179 n->t==NT_SUB && n->r->t==NT_VAR_INT &&
180 n->l != nullptr && n->l->t==NT_NONLIN
181 && n->r->a==1) {
182 (void) n->l->sum.ne->post(home,&n->r->x_int,ipls);
183 } else {
184 Int::Linear::Term<Int::IntView>* its =
185 r.alloc<Int::Linear::Term<Int::IntView> >(n->n_int);
186 int c = n->fill(home,ipls,its,nullptr);
187 Int::Linear::post(home, its, n->n_int, irt, -c,
188 (n->n_int > 2) ? ipls.linear() : ipls.linear2());
189 }
190 } else if (n->n_int == 0) {
191 // Only Boolean variables
192 Int::Linear::Term<Int::BoolView>* bts =
193 r.alloc<Int::Linear::Term<Int::BoolView> >(n->n_bool);
194 int c = n->fill(home,ipls,nullptr,bts);
195 Int::Linear::post(home, bts, n->n_bool, irt, -c,
196 (n->n_bool > 2) ? ipls.linear() : ipls.linear2());
197 } else if (n->n_bool == 1) {
198 // Integer variables and only one Boolean variable
199 Int::Linear::Term<Int::IntView>* its =
200 r.alloc<Int::Linear::Term<Int::IntView> >(n->n_int+1);
201 Int::Linear::Term<Int::BoolView>* bts =
202 r.alloc<Int::Linear::Term<Int::BoolView> >(1);
203 int c = n->fill(home,ipls,its,bts);
204 IntVar x(home,0,1);
205 channel(home,bts[0].x,x);
206 its[n->n_int].x = x;
207 its[n->n_int].a = bts[0].a;
208 Int::Linear::post(home, its, n->n_int+1, irt, -c,
209 (n->n_int > 1) ? ipls.linear() : ipls.linear2());
210 } else {
211 // Both integer and Boolean variables
212 Int::Linear::Term<Int::IntView>* its =
213 r.alloc<Int::Linear::Term<Int::IntView> >(n->n_int+1);
214 Int::Linear::Term<Int::BoolView>* bts =
215 r.alloc<Int::Linear::Term<Int::BoolView> >(n->n_bool);
216 int c = n->fill(home,ipls,its,bts);
217 int min, max;
218 Int::Linear::estimate(&bts[0],n->n_bool,0,min,max);
219 IntVar x(home,min,max);
220 its[n->n_int].x = x; its[n->n_int].a = 1;
221 Int::Linear::post(home, bts, n->n_bool, IRT_EQ, x, 0,
222 (n->n_bool > 2) ? ipls.linear() : ipls.linear2());
223 Int::Linear::post(home, its, n->n_int+1, irt, -c,
224 (n->n_int > 1) ? ipls.linear() : ipls.linear2());
225 }
226 }
227
228 void
229 LinIntExpr::post(Home home, IntRelType irt, const BoolVar& b,
230 const IntPropLevels& ipls) const {
231 if (home.failed()) return;
232 Region r;
233 if (n->n_bool == 0) {
234 // Only integer variables
235 if (n->t==NT_ADD && n->l==nullptr && n->r->t==NT_NONLIN) {
236 n->r->sum.ne->post(home,irt,-n->c,b,ipls);
237 } else if (n->t==NT_SUB && n->l==nullptr && n->r->t==NT_NONLIN) {
238 switch (irt) {
239 case IRT_LQ: irt=IRT_GQ; break;
240 case IRT_LE: irt=IRT_GR; break;
241 case IRT_GQ: irt=IRT_LQ; break;
242 case IRT_GR: irt=IRT_LE; break;
243 default: break;
244 }
245 n->r->sum.ne->post(home,irt,n->c,b,ipls);
246 } else {
247 Int::Linear::Term<Int::IntView>* its =
248 r.alloc<Int::Linear::Term<Int::IntView> >(n->n_int);
249 int c = n->fill(home,ipls,its,nullptr);
250 Int::Linear::post(home, its, n->n_int, irt, -c, b,
251 (n->n_int > 2) ? ipls.linear() : ipls.linear2());
252 }
253 } else if (n->n_int == 0) {
254 // Only Boolean variables
255 Int::Linear::Term<Int::BoolView>* bts =
256 r.alloc<Int::Linear::Term<Int::BoolView> >(n->n_bool);
257 int c = n->fill(home,ipls,nullptr,bts);
258 Int::Linear::post(home, bts, n->n_bool, irt, -c, b,
259 (n->n_bool > 2) ? ipls.linear() : ipls.linear2());
260 } else if (n->n_bool == 1) {
261 // Integer variables and only one Boolean variable
262 Int::Linear::Term<Int::IntView>* its =
263 r.alloc<Int::Linear::Term<Int::IntView> >(n->n_int+1);
264 Int::Linear::Term<Int::BoolView>* bts =
265 r.alloc<Int::Linear::Term<Int::BoolView> >(1);
266 int c = n->fill(home,ipls,its,bts);
267 IntVar x(home,0,1);
268 channel(home,bts[0].x,x);
269 its[n->n_int].x = x;
270 its[n->n_int].a = bts[0].a;
271 Int::Linear::post(home, its, n->n_int+1, irt, -c, b,
272 (n->n_int > 1) ? ipls.linear() : ipls.linear2());
273 } else {
274 // Both integer and Boolean variables
275 Int::Linear::Term<Int::IntView>* its =
276 r.alloc<Int::Linear::Term<Int::IntView> >(n->n_int+1);
277 Int::Linear::Term<Int::BoolView>* bts =
278 r.alloc<Int::Linear::Term<Int::BoolView> >(n->n_bool);
279 int c = n->fill(home,ipls,its,bts);
280 int min, max;
281 Int::Linear::estimate(&bts[0],n->n_bool,0,min,max);
282 IntVar x(home,min,max);
283 its[n->n_int].x = x; its[n->n_int].a = 1;
284 Int::Linear::post(home, bts, n->n_bool, IRT_EQ, x, 0,
285 (n->n_int > 1) ? ipls.linear() : ipls.linear2());
286 Int::Linear::post(home, its, n->n_int+1, irt, -c, b,
287 (n->n_bool > 2) ? ipls.linear() : ipls.linear2());
288 }
289 }
290
291 IntVar
292 LinIntExpr::post(Home home, const IntPropLevels& ipls) const {
293 if (home.failed()) return IntVar(home,0,0);
294 Region r;
295 if (n->n_bool == 0) {
296 // Only integer variables
297 Int::Linear::Term<Int::IntView>* its =
298 r.alloc<Int::Linear::Term<Int::IntView> >(n->n_int+1);
299 int c = n->fill(home,ipls,its,nullptr);
300 if ((n->n_int == 1) && (c == 0) && (its[0].a == 1))
301 return its[0].x;
302 int min, max;
303 Int::Linear::estimate(&its[0],n->n_int,c,min,max);
304 IntVar x(home, min, max);
305 its[n->n_int].x = x; its[n->n_int].a = -1;
306 Int::Linear::post(home, its, n->n_int+1, IRT_EQ, -c,
307 (n->n_int > 1) ? ipls.linear() : ipls.linear2());
308 return x;
309 } else if (n->n_int == 0) {
310 // Only Boolean variables
311 Int::Linear::Term<Int::BoolView>* bts =
312 r.alloc<Int::Linear::Term<Int::BoolView> >(n->n_bool);
313 int c = n->fill(home,ipls,nullptr,bts);
314 int min, max;
315 Int::Linear::estimate(&bts[0],n->n_bool,c,min,max);
316 IntVar x(home, min, max);
317 Int::Linear::post(home, bts, n->n_bool, IRT_EQ, x, -c,
318 (n->n_bool > 2) ? ipls.linear() : ipls.linear2());
319 return x;
320 } else if (n->n_bool == 1) {
321 // Integer variables and single Boolean variable
322 Int::Linear::Term<Int::IntView>* its =
323 r.alloc<Int::Linear::Term<Int::IntView> >(n->n_int+2);
324 Int::Linear::Term<Int::BoolView>* bts =
325 r.alloc<Int::Linear::Term<Int::BoolView> >(1);
326 int c = n->fill(home,ipls,its,bts);
327 IntVar x(home, 0, 1);
328 channel(home, x, bts[0].x);
329 its[n->n_int].x = x; its[n->n_int].a = bts[0].a;
330 int y_min, y_max;
331 Int::Linear::estimate(&its[0],n->n_int+1,c,y_min,y_max);
332 IntVar y(home, y_min, y_max);
333 its[n->n_int+1].x = y; its[n->n_int+1].a = -1;
334 Int::Linear::post(home, its, n->n_int+2, IRT_EQ, -c, ipls.linear());
335 return y;
336 } else {
337 // Both integer and Boolean variables
338 Int::Linear::Term<Int::IntView>* its =
339 r.alloc<Int::Linear::Term<Int::IntView> >(n->n_int+2);
340 Int::Linear::Term<Int::BoolView>* bts =
341 r.alloc<Int::Linear::Term<Int::BoolView> >(n->n_bool);
342 int c = n->fill(home,ipls,its,bts);
343 int x_min, x_max;
344 Int::Linear::estimate(&bts[0],n->n_bool,0,x_min,x_max);
345 IntVar x(home, x_min, x_max);
346 Int::Linear::post(home, bts, n->n_bool, IRT_EQ, x, 0,
347 (n->n_bool > 2) ? ipls.linear() : ipls.linear2());
348 its[n->n_int].x = x; its[n->n_int].a = 1;
349 int y_min, y_max;
350 Int::Linear::estimate(&its[0],n->n_int+1,c,y_min,y_max);
351 IntVar y(home, y_min, y_max);
352 its[n->n_int+1].x = y; its[n->n_int+1].a = -1;
353 Int::Linear::post(home, its, n->n_int+2, IRT_EQ, -c, ipls.linear());
354 return y;
355 }
356 }
357
358 NonLinIntExpr*
359 LinIntExpr::nle(void) const {
360 return n->t == NT_NONLIN ? n->sum.ne : nullptr;
361 }
362
363 LinIntExpr::LinIntExpr(void) :
364 n(new Node) {
365 n->n_int = n->n_bool = 0;
366 n->t = NT_VAR_INT;
367 n->l = n->r = nullptr;
368 n->a = 0;
369 }
370
371 LinIntExpr::LinIntExpr(int c) :
372 n(new Node) {
373 n->n_int = n->n_bool = 0;
374 n->t = NT_CONST;
375 n->l = n->r = nullptr;
376 n->a = 0;
377 Int::Limits::check(c,"MiniModel::LinIntExpr");
378 n->c = c;
379 }
380
381 LinIntExpr::LinIntExpr(const IntVar& x, int a) :
382 n(new Node) {
383 n->n_int = 1;
384 n->n_bool = 0;
385 n->t = NT_VAR_INT;
386 n->l = n->r = nullptr;
387 n->a = a;
388 n->x_int = x;
389 }
390
391 LinIntExpr::LinIntExpr(const BoolVar& x, int a) :
392 n(new Node) {
393 n->n_int = 0;
394 n->n_bool = 1;
395 n->t = NT_VAR_BOOL;
396 n->l = n->r = nullptr;
397 n->a = a;
398 n->x_bool = x;
399 }
400
401 LinIntExpr::LinIntExpr(const IntVarArgs& x) :
402 n(new Node) {
403 n->n_int = x.size();
404 n->n_bool = 0;
405 n->t = NT_SUM_INT;
406 n->l = n->r = nullptr;
407 if (x.size() > 0) {
408 n->sum.ti = heap.alloc<Int::Linear::Term<Int::IntView> >(x.size());
409 for (int i=x.size(); i--; ) {
410 n->sum.ti[i].x = x[i];
411 n->sum.ti[i].a = 1;
412 }
413 }
414 }
415
416 LinIntExpr::LinIntExpr(const IntArgs& a, const IntVarArgs& x) :
417 n(new Node) {
418 if (a.size() != x.size())
419 throw Int::ArgumentSizeMismatch("MiniModel::LinIntExpr");
420 n->n_int = x.size();
421 n->n_bool = 0;
422 n->t = NT_SUM_INT;
423 n->l = n->r = nullptr;
424 if (x.size() > 0) {
425 n->sum.ti = heap.alloc<Int::Linear::Term<Int::IntView> >(x.size());
426 for (int i=x.size(); i--; ) {
427 n->sum.ti[i].x = x[i];
428 n->sum.ti[i].a = a[i];
429 }
430 }
431 }
432
433 LinIntExpr::LinIntExpr(const BoolVarArgs& x) :
434 n(new Node) {
435 n->n_int = 0;
436 n->n_bool = x.size();
437 n->t = NT_SUM_BOOL;
438 n->l = n->r = nullptr;
439 if (x.size() > 0) {
440 n->sum.tb = heap.alloc<Int::Linear::Term<Int::BoolView> >(x.size());
441 for (int i=x.size(); i--; ) {
442 n->sum.tb[i].x = x[i];
443 n->sum.tb[i].a = 1;
444 }
445 }
446 }
447
448 LinIntExpr::LinIntExpr(const IntArgs& a, const BoolVarArgs& x) :
449 n(new Node) {
450 if (a.size() != x.size())
451 throw Int::ArgumentSizeMismatch("MiniModel::LinIntExpr");
452 n->n_int = 0;
453 n->n_bool = x.size();
454 n->t = NT_SUM_BOOL;
455 n->l = n->r = nullptr;
456 if (x.size() > 0) {
457 n->sum.tb = heap.alloc<Int::Linear::Term<Int::BoolView> >(x.size());
458 for (int i=x.size(); i--; ) {
459 n->sum.tb[i].x = x[i];
460 n->sum.tb[i].a = a[i];
461 }
462 }
463 }
464
465 LinIntExpr::LinIntExpr(const LinIntExpr& e0, NodeType t, const LinIntExpr& e1) :
466 n(new Node) {
467 n->n_int = e0.n->n_int + e1.n->n_int;
468 n->n_bool = e0.n->n_bool + e1.n->n_bool;
469 n->t = t;
470 n->l = e0.n; n->l->use++;
471 n->r = e1.n; n->r->use++;
472 }
473
474 LinIntExpr::LinIntExpr(const LinIntExpr& e, NodeType t, int c) :
475 n(new Node) {
476 n->n_int = e.n->n_int;
477 n->n_bool = e.n->n_bool;
478 n->t = t;
479 n->l = nullptr;
480 n->r = e.n; n->r->use++;
481 n->c = c;
482 }
483
484 LinIntExpr::LinIntExpr(int a, const LinIntExpr& e) :
485 n(new Node) {
486 n->n_int = e.n->n_int;
487 n->n_bool = e.n->n_bool;
488 n->t = NT_MUL;
489 n->l = e.n; n->l->use++;
490 n->r = nullptr;
491 n->a = a;
492 }
493
494 LinIntExpr::LinIntExpr(NonLinIntExpr* e) :
495 n(new Node) {
496 n->n_int = 1;
497 n->n_bool = 0;
498 n->t = NT_NONLIN;
499 n->l = n->r = nullptr;
500 n->a = 0;
501 n->sum.ne = e;
502 }
503
504 const LinIntExpr&
505 LinIntExpr::operator =(const LinIntExpr& e) {
506 if (this != &e) {
507 if (n->decrement())
508 delete n;
509 n = e.n; n->use++;
510 }
511 return *this;
512 }
513
514 LinIntExpr::~LinIntExpr(void) {
515 if (n->decrement())
516 delete n;
517 }
518
519
520 void
521 LinIntExpr::Node::fill(Home home, const IntPropLevels& ipls,
522 Int::Linear::Term<Int::IntView>*& ti,
523 Int::Linear::Term<Int::BoolView>*& tb,
524 long long int m, long long int& d) const {
525 switch (this->t) {
526 case NT_CONST:
527 Int::Limits::check(m*c,"MiniModel::LinIntExpr");
528 d += m*c;
529 break;
530 case NT_VAR_INT:
531 Int::Limits::check(m*a,"MiniModel::LinIntExpr");
532 ti->a=static_cast<int>(m*a); ti->x=x_int; ti++;
533 break;
534 case NT_NONLIN:
535 ti->a=static_cast<int>(m); ti->x=sum.ne->post(home, nullptr, ipls); ti++;
536 break;
537 case NT_VAR_BOOL:
538 Int::Limits::check(m*a,"MiniModel::LinIntExpr");
539 tb->a=static_cast<int>(m*a); tb->x=x_bool; tb++;
540 break;
541 case NT_SUM_INT:
542 for (int i=n_int; i--; ) {
543 Int::Limits::check(m*sum.ti[i].a,"MiniModel::LinIntExpr");
544 ti[i].x = sum.ti[i].x; ti[i].a = static_cast<int>(m*sum.ti[i].a);
545 }
546 ti += n_int;
547 break;
548 case NT_SUM_BOOL:
549 for (int i=n_bool; i--; ) {
550 Int::Limits::check(m*sum.tb[i].a,"MiniModel::LinIntExpr");
551 tb[i].x = sum.tb[i].x; tb[i].a = static_cast<int>(m*sum.tb[i].a);
552 }
553 tb += n_bool;
554 break;
555 case NT_ADD:
556 if (l == nullptr) {
557 Int::Limits::check(m*c,"MiniModel::LinIntExpr");
558 d += m*c;
559 } else {
560 l->fill(home,ipls,ti,tb,m,d);
561 }
562 r->fill(home,ipls,ti,tb,m,d);
563 break;
564 case NT_SUB:
565 if (l == nullptr) {
566 Int::Limits::check(m*c,"MiniModel::LinIntExpr");
567 d += m*c;
568 } else {
569 l->fill(home,ipls,ti,tb,m,d);
570 }
571 r->fill(home,ipls,ti,tb,-m,d);
572 break;
573 case NT_MUL:
574 Int::Limits::check(m*a,"MiniModel::LinIntExpr");
575 l->fill(home,ipls,ti,tb,m*a,d);
576 break;
577 default:
578 GECODE_NEVER;
579 }
580 }
581
582
583 /*
584 * Operators
585 *
586 */
587 LinIntExpr
588 operator +(int c, const IntVar& x) {
589 if (x.assigned() &&
590 Int::Limits::valid(static_cast<long long int>(c)+x.val()))
591 return LinIntExpr(c+x.val());
592 else
593 return LinIntExpr(x,LinIntExpr::NT_ADD,c);
594 }
595 LinIntExpr
596 operator +(int c, const BoolVar& x) {
597 if (x.assigned() &&
598 Int::Limits::valid(static_cast<long long int>(c)+x.val()))
599 return LinIntExpr(c+x.val());
600 else
601 return LinIntExpr(x,LinIntExpr::NT_ADD,c);
602 }
603 LinIntExpr
604 operator +(int c, const LinIntExpr& e) {
605 return LinIntExpr(e,LinIntExpr::NT_ADD,c);
606 }
607 LinIntExpr
608 operator +(const IntVar& x, int c) {
609 if (x.assigned() &&
610 Int::Limits::valid(static_cast<long long int>(c)+x.val()))
611 return LinIntExpr(c+x.val());
612 else
613 return LinIntExpr(x,LinIntExpr::NT_ADD,c);
614 }
615 LinIntExpr
616 operator +(const BoolVar& x, int c) {
617 if (x.assigned() &&
618 Int::Limits::valid(static_cast<long long int>(c)+x.val()))
619 return LinIntExpr(c+x.val());
620 else
621 return LinIntExpr(x,LinIntExpr::NT_ADD,c);
622 }
623 LinIntExpr
624 operator +(const LinIntExpr& e, int c) {
625 return LinIntExpr(e,LinIntExpr::NT_ADD,c);
626 }
627 LinIntExpr
628 operator +(const IntVar& x, const IntVar& y) {
629 if (x.assigned())
630 return x.val() + y;
631 else if (y.assigned())
632 return x + y.val();
633 else
634 return LinIntExpr(x,LinIntExpr::NT_ADD,y);
635 }
636 LinIntExpr
637 operator +(const IntVar& x, const BoolVar& y) {
638 if (x.assigned())
639 return x.val() + y;
640 else if (y.assigned())
641 return x + y.val();
642 else
643 return LinIntExpr(x,LinIntExpr::NT_ADD,y);
644 }
645 LinIntExpr
646 operator +(const BoolVar& x, const IntVar& y) {
647 if (x.assigned())
648 return x.val() + y;
649 else if (y.assigned())
650 return x + y.val();
651 else
652 return LinIntExpr(x,LinIntExpr::NT_ADD,y);
653 }
654 LinIntExpr
655 operator +(const BoolVar& x, const BoolVar& y) {
656 if (x.assigned())
657 return x.val() + y;
658 else if (y.assigned())
659 return x + y.val();
660 else
661 return LinIntExpr(x,LinIntExpr::NT_ADD,y);
662 }
663 LinIntExpr
664 operator +(const IntVar& x, const LinIntExpr& e) {
665 if (x.assigned())
666 return x.val() + e;
667 else
668 return LinIntExpr(x,LinIntExpr::NT_ADD,e);
669 }
670 LinIntExpr
671 operator +(const BoolVar& x, const LinIntExpr& e) {
672 if (x.assigned())
673 return x.val() + e;
674 else
675 return LinIntExpr(x,LinIntExpr::NT_ADD,e);
676 }
677 LinIntExpr
678 operator +(const LinIntExpr& e, const IntVar& x) {
679 if (x.assigned())
680 return e + x.val();
681 else
682 return LinIntExpr(e,LinIntExpr::NT_ADD,x);
683 }
684 LinIntExpr
685 operator +(const LinIntExpr& e, const BoolVar& x) {
686 if (x.assigned())
687 return e + x.val();
688 else
689 return LinIntExpr(e,LinIntExpr::NT_ADD,x);
690 }
691 LinIntExpr
692 operator +(const LinIntExpr& e1, const LinIntExpr& e2) {
693 return LinIntExpr(e1,LinIntExpr::NT_ADD,e2);
694 }
695
696 LinIntExpr
697 operator -(int c, const IntVar& x) {
698 if (x.assigned() &&
699 Int::Limits::valid(static_cast<long long int>(c)-x.val()))
700 return LinIntExpr(c-x.val());
701 else
702 return LinIntExpr(x,LinIntExpr::NT_SUB,c);
703 }
704 LinIntExpr
705 operator -(int c, const BoolVar& x) {
706 if (x.assigned() &&
707 Int::Limits::valid(static_cast<long long int>(c)-x.val()))
708 return LinIntExpr(c-x.val());
709 else
710 return LinIntExpr(x,LinIntExpr::NT_SUB,c);
711 }
712 LinIntExpr
713 operator -(int c, const LinIntExpr& e) {
714 return LinIntExpr(e,LinIntExpr::NT_SUB,c);
715 }
716 LinIntExpr
717 operator -(const IntVar& x, int c) {
718 if (x.assigned() &&
719 Int::Limits::valid(x.val()-static_cast<long long int>(c)))
720 return LinIntExpr(x.val()-c);
721 else
722 return LinIntExpr(x,LinIntExpr::NT_ADD,-c);
723 }
724 LinIntExpr
725 operator -(const BoolVar& x, int c) {
726 if (x.assigned() &&
727 Int::Limits::valid(x.val()-static_cast<long long int>(c)))
728 return LinIntExpr(x.val()-c);
729 else
730 return LinIntExpr(x,LinIntExpr::NT_ADD,-c);
731 }
732 LinIntExpr
733 operator -(const LinIntExpr& e, int c) {
734 return LinIntExpr(e,LinIntExpr::NT_ADD,-c);
735 }
736 LinIntExpr
737 operator -(const IntVar& x, const IntVar& y) {
738 if (x.assigned())
739 return x.val() - y;
740 else if (y.assigned())
741 return x - y.val();
742 else
743 return LinIntExpr(x,LinIntExpr::NT_SUB,y);
744 }
745 LinIntExpr
746 operator -(const IntVar& x, const BoolVar& y) {
747 if (x.assigned())
748 return x.val() - y;
749 else if (y.assigned())
750 return x - y.val();
751 else
752 return LinIntExpr(x,LinIntExpr::NT_SUB,y);
753 }
754 LinIntExpr
755 operator -(const BoolVar& x, const IntVar& y) {
756 if (x.assigned())
757 return x.val() - y;
758 else if (y.assigned())
759 return x - y.val();
760 else
761 return LinIntExpr(x,LinIntExpr::NT_SUB,y);
762 }
763 LinIntExpr
764 operator -(const BoolVar& x, const BoolVar& y) {
765 if (x.assigned())
766 return x.val() - y;
767 else if (y.assigned())
768 return x - y.val();
769 else
770 return LinIntExpr(x,LinIntExpr::NT_SUB,y);
771 }
772 LinIntExpr
773 operator -(const IntVar& x, const LinIntExpr& e) {
774 if (x.assigned())
775 return x.val() - e;
776 else
777 return LinIntExpr(x,LinIntExpr::NT_SUB,e);
778 }
779 LinIntExpr
780 operator -(const BoolVar& x, const LinIntExpr& e) {
781 if (x.assigned())
782 return x.val() - e;
783 else
784 return LinIntExpr(x,LinIntExpr::NT_SUB,e);
785 }
786 LinIntExpr
787 operator -(const LinIntExpr& e, const IntVar& x) {
788 if (x.assigned())
789 return e - x.val();
790 else
791 return LinIntExpr(e,LinIntExpr::NT_SUB,x);
792 }
793 LinIntExpr
794 operator -(const LinIntExpr& e, const BoolVar& x) {
795 if (x.assigned())
796 return e - x.val();
797 else
798 return LinIntExpr(e,LinIntExpr::NT_SUB,x);
799 }
800 LinIntExpr
801 operator -(const LinIntExpr& e1, const LinIntExpr& e2) {
802 return LinIntExpr(e1,LinIntExpr::NT_SUB,e2);
803 }
804
805 LinIntExpr
806 operator -(const IntVar& x) {
807 if (x.assigned())
808 return LinIntExpr(-x.val());
809 else
810 return LinIntExpr(x,LinIntExpr::NT_SUB,0);
811 }
812 LinIntExpr
813 operator -(const BoolVar& x) {
814 if (x.assigned())
815 return LinIntExpr(-x.val());
816 else
817 return LinIntExpr(x,LinIntExpr::NT_SUB,0);
818 }
819 LinIntExpr
820 operator -(const LinIntExpr& e) {
821 return LinIntExpr(e,LinIntExpr::NT_SUB,0);
822 }
823
824 LinIntExpr
825 operator *(int a, const IntVar& x) {
826 if (a == 0)
827 return LinIntExpr(0);
828 else if (x.assigned() &&
829 Int::Limits::valid(static_cast<long long int>(a)*x.val()))
830 return LinIntExpr(a*x.val());
831 else
832 return LinIntExpr(x,a);
833 }
834 LinIntExpr
835 operator *(int a, const BoolVar& x) {
836 if (a == 0)
837 return LinIntExpr(0);
838 else if (x.assigned() &&
839 Int::Limits::valid(static_cast<long long int>(a)*x.val()))
840 return LinIntExpr(a*x.val());
841 else
842 return LinIntExpr(x,a);
843 }
844 LinIntExpr
845 operator *(const IntVar& x, int a) {
846 if (a == 0)
847 return LinIntExpr(0);
848 else if (x.assigned() &&
849 Int::Limits::valid(static_cast<long long int>(a)*x.val()))
850 return LinIntExpr(a*x.val());
851 else
852 return LinIntExpr(x,a);
853 }
854 LinIntExpr
855 operator *(const BoolVar& x, int a) {
856 if (a == 0)
857 return LinIntExpr(0);
858 else if (x.assigned() &&
859 Int::Limits::valid(static_cast<long long int>(a)*x.val()))
860 return LinIntExpr(a*x.val());
861 else
862 return LinIntExpr(x,a);
863 }
864 LinIntExpr
865 operator *(const LinIntExpr& e, int a) {
866 if (a == 0)
867 return LinIntExpr(0);
868 else
869 return LinIntExpr(a,e);
870 }
871 LinIntExpr
872 operator *(int a, const LinIntExpr& e) {
873 if (a == 0)
874 return LinIntExpr(0);
875 else
876 return LinIntExpr(a,e);
877 }
878
879 LinIntExpr
880 sum(const IntVarArgs& x) {
881 return LinIntExpr(x);
882 }
883 LinIntExpr
884 sum(const IntArgs& a, const IntVarArgs& x) {
885 return LinIntExpr(a,x);
886 }
887 LinIntExpr
888 sum(const BoolVarArgs& x) {
889 return LinIntExpr(x);
890 }
891 LinIntExpr
892 sum(const IntArgs& a, const BoolVarArgs& x) {
893 return LinIntExpr(a,x);
894 }
895 LinIntExpr
896 sum(const Slice<IntArgs>& slice) {
897 const Slice<IntArgs>::ArgsType & args = slice;
898 return sum(args);
899 }
900 LinIntExpr
901 sum(const Matrix<IntArgs>& matrix) {
902 const Matrix<IntArgs>::ArgsType & args = matrix.get_array();
903 return sum(args);
904 }
905 LinIntExpr
906 sum(const IntArgs& args) {
907 int sum = 0;
908 for (int i = 0; i<args.size(); i++)
909 sum += args[i];
910 return LinIntExpr(sum);
911 }
912
913
914 IntVar
915 expr(Home home, const LinIntExpr& e, const IntPropLevels& ipls) {
916 PostInfo pi(home);
917 if (!home.failed())
918 return e.post(home,ipls);
919 IntVar x(home,Int::Limits::min,Int::Limits::max);
920 return x;
921 }
922
923}
924
925// STATISTICS: minimodel-any