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