Generated on Tue Apr 18 10:22:08 2017 for Gecode by doxygen 1.6.3

int-expr.cpp

Go to the documentation of this file.
00001 /* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
00002 /*
00003  *  Main authors:
00004  *     Christian Schulte <schulte@gecode.org>
00005  *
00006  *  Copyright:
00007  *     Christian Schulte, 2010
00008  *
00009  *  Last modified:
00010  *     $Date: 2016-08-08 16:24:17 +0200 (Mon, 08 Aug 2016) $ by $Author: schulte $
00011  *     $Revision: 15141 $
00012  *
00013  *  This file is part of Gecode, the generic constraint
00014  *  development environment:
00015  *     http://www.gecode.org
00016  *
00017  *  Permission is hereby granted, free of charge, to any person obtaining
00018  *  a copy of this software and associated documentation files (the
00019  *  "Software"), to deal in the Software without restriction, including
00020  *  without limitation the rights to use, copy, modify, merge, publish,
00021  *  distribute, sublicense, and/or sell copies of the Software, and to
00022  *  permit persons to whom the Software is furnished to do so, subject to
00023  *  the following conditions:
00024  *
00025  *  The above copyright notice and this permission notice shall be
00026  *  included in all copies or substantial portions of the Software.
00027  *
00028  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00029  *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00030  *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00031  *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
00032  *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
00033  *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
00034  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00035  *
00036  */
00037 
00038 #include <gecode/minimodel.hh>
00039 #include <gecode/int/linear.hh>
00040 
00041 namespace Gecode {
00042 
00044   class LinIntExpr::Node {
00045   public:
00047     unsigned int use;
00049     int n_int;
00051     int n_bool;
00053     NodeType t;
00055     Node *l, *r;
00057     union {
00059       Int::Linear::Term<Int::IntView>* ti;
00061       Int::Linear::Term<Int::BoolView>* tb;
00063       NonLinIntExpr* ne;
00064     } sum;
00066     int a, c;
00068     IntVar x_int;
00070     BoolVar x_bool;
00072     Node(void);
00074     void fill(Home home, IntPropLevel ipl,
00075               Int::Linear::Term<Int::IntView>*& ti,
00076               Int::Linear::Term<Int::BoolView>*& tb,
00077               long long int m, long long int& d) const;
00079     int fill(Home home, IntPropLevel ipl,
00080              Int::Linear::Term<Int::IntView>* ti,
00081              Int::Linear::Term<Int::BoolView>* tb) const;
00083     bool decrement(void);
00085     ~Node(void);
00087     static void* operator new(size_t size);
00089     static void  operator delete(void* p,size_t size);
00090   };
00091 
00092   /*
00093    * Operations for nodes
00094    *
00095    */
00096   forceinline
00097   LinIntExpr::Node::Node(void) : use(1) {
00098   }
00099 
00100   forceinline
00101   LinIntExpr::Node::~Node(void) {
00102     switch (t) {
00103     case NT_SUM_INT:
00104       if (n_int > 0)
00105         heap.free<Int::Linear::Term<Int::IntView> >(sum.ti,n_int);
00106       break;
00107     case NT_SUM_BOOL:
00108       if (n_bool > 0)
00109         heap.free<Int::Linear::Term<Int::BoolView> >(sum.tb,n_bool);
00110       break;
00111     case NT_NONLIN:
00112       delete sum.ne;
00113       break;
00114     default: ;
00115     }
00116   }
00117 
00118   forceinline void*
00119   LinIntExpr::Node::operator new(size_t size) {
00120     return heap.ralloc(size);
00121   }
00122 
00123   forceinline void
00124   LinIntExpr::Node::operator delete(void* p, size_t) {
00125     heap.rfree(p);
00126   }
00127   bool
00128   LinIntExpr::Node::decrement(void) {
00129     if (--use == 0) {
00130       if ((l != NULL) && l->decrement())
00131         delete l;
00132       if ((r != NULL) && r->decrement())
00133         delete r;
00134       return true;
00135     }
00136     return false;
00137   }
00138 
00139   /*
00140    * Operations for expressions
00141    *
00142    */
00143 
00144   LinIntExpr::LinIntExpr(const LinIntExpr& e)
00145     : n(e.n) {
00146     n->use++;
00147   }
00148 
00149   int
00150   LinIntExpr::Node::fill(Home home, IntPropLevel ipl,
00151                       Int::Linear::Term<Int::IntView>* ti,
00152                       Int::Linear::Term<Int::BoolView>* tb) const {
00153     long long int d=0;
00154     fill(home,ipl,ti,tb,1,d);
00155     Int::Limits::check(d,"MiniModel::LinIntExpr");
00156     return static_cast<int>(d);
00157   }
00158 
00159   void
00160   LinIntExpr::post(Home home, IntRelType irt, IntPropLevel ipl) const {
00161     if (home.failed()) return;
00162     Region r(home);
00163     if (n->n_bool == 0) {
00164       // Only integer variables
00165       if (n->t==NT_ADD && n->l == NULL && n->r->t==NT_NONLIN) {
00166         n->r->sum.ne->post(home,irt,-n->c,ipl);
00167       } else if (n->t==NT_SUB && n->r->t==NT_NONLIN && n->l==NULL) {
00168         switch (irt) {
00169         case IRT_LQ: irt=IRT_GQ; break;
00170         case IRT_LE: irt=IRT_GR; break;
00171         case IRT_GQ: irt=IRT_LQ; break;
00172         case IRT_GR: irt=IRT_LE; break;
00173         default: break;
00174         }
00175         n->r->sum.ne->post(home,irt,n->c,ipl);
00176       } else if (irt==IRT_EQ &&
00177                  n->t==NT_SUB && n->r->t==NT_NONLIN &&
00178                  n->l != NULL && n->l->t==NT_VAR_INT
00179                  && n->l->a==1) {
00180         (void) n->r->sum.ne->post(home,&n->l->x_int,ipl);
00181       } else if (irt==IRT_EQ &&
00182                  n->t==NT_SUB && n->r->t==NT_VAR_INT &&
00183                  n->l != NULL && n->l->t==NT_NONLIN
00184                  && n->r->a==1) {
00185         (void) n->l->sum.ne->post(home,&n->r->x_int,ipl);
00186       } else {
00187         Int::Linear::Term<Int::IntView>* its =
00188           r.alloc<Int::Linear::Term<Int::IntView> >(n->n_int);
00189         int c = n->fill(home,ipl,its,NULL);
00190         Int::Linear::post(home, its, n->n_int, irt, -c, ipl);
00191       }
00192     } else if (n->n_int == 0) {
00193       // Only Boolean variables
00194       Int::Linear::Term<Int::BoolView>* bts =
00195         r.alloc<Int::Linear::Term<Int::BoolView> >(n->n_bool);
00196       int c = n->fill(home,ipl,NULL,bts);
00197       Int::Linear::post(home, bts, n->n_bool, irt, -c, ipl);
00198     } else if (n->n_bool == 1) {
00199       // Integer variables and only one Boolean variable
00200       Int::Linear::Term<Int::IntView>* its =
00201         r.alloc<Int::Linear::Term<Int::IntView> >(n->n_int+1);
00202       Int::Linear::Term<Int::BoolView>* bts =
00203         r.alloc<Int::Linear::Term<Int::BoolView> >(1);
00204       int c = n->fill(home,ipl,its,bts);
00205       IntVar x(home,0,1);
00206       channel(home,bts[0].x,x);
00207       its[n->n_int].x = x;
00208       its[n->n_int].a = bts[0].a;
00209       Int::Linear::post(home, its, n->n_int+1, irt, -c, ipl);
00210     } else {
00211       // Both integer and Boolean variables
00212       Int::Linear::Term<Int::IntView>* its =
00213         r.alloc<Int::Linear::Term<Int::IntView> >(n->n_int+1);
00214       Int::Linear::Term<Int::BoolView>* bts =
00215         r.alloc<Int::Linear::Term<Int::BoolView> >(n->n_bool);
00216       int c = n->fill(home,ipl,its,bts);
00217       int min, max;
00218       Int::Linear::estimate(&bts[0],n->n_bool,0,min,max);
00219       IntVar x(home,min,max);
00220       its[n->n_int].x = x; its[n->n_int].a = 1;
00221       Int::Linear::post(home, bts, n->n_bool, IRT_EQ, x, 0, ipl);
00222       Int::Linear::post(home, its, n->n_int+1, irt, -c, ipl);
00223     }
00224   }
00225 
00226   void
00227   LinIntExpr::post(Home home, IntRelType irt, const BoolVar& b,
00228                 IntPropLevel ipl) const {
00229     if (home.failed()) return;
00230     Region r(home);
00231     if (n->n_bool == 0) {
00232       // Only integer variables
00233       if (n->t==NT_ADD && n->l==NULL && n->r->t==NT_NONLIN) {
00234         n->r->sum.ne->post(home,irt,-n->c,b,ipl);
00235       } else if (n->t==NT_SUB && n->l==NULL && n->r->t==NT_NONLIN) {
00236         switch (irt) {
00237         case IRT_LQ: irt=IRT_GQ; break;
00238         case IRT_LE: irt=IRT_GR; break;
00239         case IRT_GQ: irt=IRT_LQ; break;
00240         case IRT_GR: irt=IRT_LE; break;
00241         default: break;
00242         }
00243         n->r->sum.ne->post(home,irt,n->c,b,ipl);
00244       } else {
00245         Int::Linear::Term<Int::IntView>* its =
00246           r.alloc<Int::Linear::Term<Int::IntView> >(n->n_int);
00247         int c = n->fill(home,ipl,its,NULL);
00248         Int::Linear::post(home, its, n->n_int, irt, -c, b, ipl);
00249       }
00250     } else if (n->n_int == 0) {
00251       // Only Boolean variables
00252       Int::Linear::Term<Int::BoolView>* bts =
00253         r.alloc<Int::Linear::Term<Int::BoolView> >(n->n_bool);
00254       int c = n->fill(home,ipl,NULL,bts);
00255       Int::Linear::post(home, bts, n->n_bool, irt, -c, b, ipl);
00256     } else if (n->n_bool == 1) {
00257       // Integer variables and only one Boolean variable
00258       Int::Linear::Term<Int::IntView>* its =
00259         r.alloc<Int::Linear::Term<Int::IntView> >(n->n_int+1);
00260       Int::Linear::Term<Int::BoolView>* bts =
00261         r.alloc<Int::Linear::Term<Int::BoolView> >(1);
00262       int c = n->fill(home,ipl,its,bts);
00263       IntVar x(home,0,1);
00264       channel(home,bts[0].x,x);
00265       its[n->n_int].x = x;
00266       its[n->n_int].a = bts[0].a;
00267       Int::Linear::post(home, its, n->n_int+1, irt, -c, b, ipl);
00268     } else {
00269       // Both integer and Boolean variables
00270       Int::Linear::Term<Int::IntView>* its =
00271         r.alloc<Int::Linear::Term<Int::IntView> >(n->n_int+1);
00272       Int::Linear::Term<Int::BoolView>* bts =
00273         r.alloc<Int::Linear::Term<Int::BoolView> >(n->n_bool);
00274       int c = n->fill(home,ipl,its,bts);
00275       int min, max;
00276       Int::Linear::estimate(&bts[0],n->n_bool,0,min,max);
00277       IntVar x(home,min,max);
00278       its[n->n_int].x = x; its[n->n_int].a = 1;
00279       Int::Linear::post(home, bts, n->n_bool, IRT_EQ, x, 0, ipl);
00280       Int::Linear::post(home, its, n->n_int+1, irt, -c, b, ipl);
00281     }
00282   }
00283 
00284   IntVar
00285   LinIntExpr::post(Home home, IntPropLevel ipl) const {
00286     if (home.failed()) return IntVar(home,0,0);
00287     Region r(home);
00288     if (n->n_bool == 0) {
00289       // Only integer variables
00290       Int::Linear::Term<Int::IntView>* its =
00291         r.alloc<Int::Linear::Term<Int::IntView> >(n->n_int+1);
00292       int c = n->fill(home,ipl,its,NULL);
00293       if ((n->n_int == 1) && (c == 0) && (its[0].a == 1))
00294         return its[0].x;
00295       int min, max;
00296       Int::Linear::estimate(&its[0],n->n_int,c,min,max);
00297       IntVar x(home, min, max);
00298       its[n->n_int].x = x; its[n->n_int].a = -1;
00299       Int::Linear::post(home, its, n->n_int+1, IRT_EQ, -c, ipl);
00300       return x;
00301     } else if (n->n_int == 0) {
00302       // Only Boolean variables
00303       Int::Linear::Term<Int::BoolView>* bts =
00304         r.alloc<Int::Linear::Term<Int::BoolView> >(n->n_bool);
00305       int c = n->fill(home,ipl,NULL,bts);
00306       int min, max;
00307       Int::Linear::estimate(&bts[0],n->n_bool,c,min,max);
00308       IntVar x(home, min, max);
00309       Int::Linear::post(home, bts, n->n_bool, IRT_EQ, x, -c, ipl);
00310       return x;
00311     } else if (n->n_bool == 1) {
00312       // Integer variables and single Boolean variable
00313       Int::Linear::Term<Int::IntView>* its =
00314         r.alloc<Int::Linear::Term<Int::IntView> >(n->n_int+2);
00315       Int::Linear::Term<Int::BoolView>* bts =
00316         r.alloc<Int::Linear::Term<Int::BoolView> >(1);
00317       int c = n->fill(home,ipl,its,bts);
00318       IntVar x(home, 0, 1);
00319       channel(home, x, bts[0].x);
00320       its[n->n_int].x = x; its[n->n_int].a = bts[0].a;
00321       int y_min, y_max;
00322       Int::Linear::estimate(&its[0],n->n_int+1,c,y_min,y_max);
00323       IntVar y(home, y_min, y_max);
00324       its[n->n_int+1].x = y; its[n->n_int+1].a = -1;
00325       Int::Linear::post(home, its, n->n_int+2, IRT_EQ, -c, ipl);
00326       return y;
00327     } else {
00328       // Both integer and Boolean variables
00329       Int::Linear::Term<Int::IntView>* its =
00330         r.alloc<Int::Linear::Term<Int::IntView> >(n->n_int+2);
00331       Int::Linear::Term<Int::BoolView>* bts =
00332         r.alloc<Int::Linear::Term<Int::BoolView> >(n->n_bool);
00333       int c = n->fill(home,ipl,its,bts);
00334       int x_min, x_max;
00335       Int::Linear::estimate(&bts[0],n->n_bool,0,x_min,x_max);
00336       IntVar x(home, x_min, x_max);
00337       Int::Linear::post(home, bts, n->n_bool, IRT_EQ, x, 0, ipl);
00338       its[n->n_int].x = x; its[n->n_int].a = 1;
00339       int y_min, y_max;
00340       Int::Linear::estimate(&its[0],n->n_int+1,c,y_min,y_max);
00341       IntVar y(home, y_min, y_max);
00342       its[n->n_int+1].x = y; its[n->n_int+1].a = -1;
00343       Int::Linear::post(home, its, n->n_int+2, IRT_EQ, -c, ipl);
00344       return y;
00345     }
00346   }
00347 
00348   NonLinIntExpr*
00349   LinIntExpr::nle(void) const {
00350     return n->t == NT_NONLIN ? n->sum.ne : NULL;
00351   }
00352 
00353   LinIntExpr::LinIntExpr(void) :
00354     n(new Node) {
00355     n->n_int = n->n_bool = 0;
00356     n->t = NT_VAR_INT;
00357     n->l = n->r = NULL;
00358     n->a = 0;
00359   }
00360 
00361   LinIntExpr::LinIntExpr(int c) :
00362     n(new Node) {
00363     n->n_int = n->n_bool = 0;
00364     n->t = NT_CONST;
00365     n->l = n->r = NULL;
00366     n->a = 0;
00367     Int::Limits::check(c,"MiniModel::LinIntExpr");
00368     n->c = c;
00369   }
00370 
00371   LinIntExpr::LinIntExpr(const IntVar& x, int a) :
00372     n(new Node) {
00373     n->n_int = 1;
00374     n->n_bool = 0;
00375     n->t = NT_VAR_INT;
00376     n->l = n->r = NULL;
00377     n->a = a;
00378     n->x_int = x;
00379   }
00380 
00381   LinIntExpr::LinIntExpr(const BoolVar& x, int a) :
00382     n(new Node) {
00383     n->n_int = 0;
00384     n->n_bool = 1;
00385     n->t = NT_VAR_BOOL;
00386     n->l = n->r = NULL;
00387     n->a = a;
00388     n->x_bool = x;
00389   }
00390 
00391   LinIntExpr::LinIntExpr(const IntVarArgs& x) :
00392     n(new Node) {
00393     n->n_int = x.size();
00394     n->n_bool = 0;
00395     n->t = NT_SUM_INT;
00396     n->l = n->r = NULL;
00397     if (x.size() > 0) {
00398       n->sum.ti = heap.alloc<Int::Linear::Term<Int::IntView> >(x.size());
00399       for (int i=x.size(); i--; ) {
00400         n->sum.ti[i].x = x[i];
00401         n->sum.ti[i].a = 1;
00402       }
00403     }
00404   }
00405 
00406   LinIntExpr::LinIntExpr(const IntArgs& a, const IntVarArgs& x) :
00407     n(new Node) {
00408     if (a.size() != x.size())
00409       throw Int::ArgumentSizeMismatch("MiniModel::LinIntExpr");
00410     n->n_int = x.size();
00411     n->n_bool = 0;
00412     n->t = NT_SUM_INT;
00413     n->l = n->r = NULL;
00414     if (x.size() > 0) {
00415       n->sum.ti = heap.alloc<Int::Linear::Term<Int::IntView> >(x.size());
00416       for (int i=x.size(); i--; ) {
00417         n->sum.ti[i].x = x[i];
00418         n->sum.ti[i].a = a[i];
00419       }
00420     }
00421   }
00422 
00423   LinIntExpr::LinIntExpr(const BoolVarArgs& x) :
00424     n(new Node) {
00425     n->n_int = 0;
00426     n->n_bool = x.size();
00427     n->t = NT_SUM_BOOL;
00428     n->l = n->r = NULL;
00429     if (x.size() > 0) {
00430       n->sum.tb = heap.alloc<Int::Linear::Term<Int::BoolView> >(x.size());
00431       for (int i=x.size(); i--; ) {
00432         n->sum.tb[i].x = x[i];
00433         n->sum.tb[i].a = 1;
00434       }
00435     }
00436   }
00437 
00438   LinIntExpr::LinIntExpr(const IntArgs& a, const BoolVarArgs& x) :
00439     n(new Node) {
00440     if (a.size() != x.size())
00441       throw Int::ArgumentSizeMismatch("MiniModel::LinIntExpr");
00442     n->n_int = 0;
00443     n->n_bool = x.size();
00444     n->t = NT_SUM_BOOL;
00445     n->l = n->r = NULL;
00446     if (x.size() > 0) {
00447       n->sum.tb = heap.alloc<Int::Linear::Term<Int::BoolView> >(x.size());
00448       for (int i=x.size(); i--; ) {
00449         n->sum.tb[i].x = x[i];
00450         n->sum.tb[i].a = a[i];
00451       }
00452     }
00453   }
00454 
00455   LinIntExpr::LinIntExpr(const LinIntExpr& e0, NodeType t, const LinIntExpr& e1) :
00456     n(new Node) {
00457     n->n_int = e0.n->n_int + e1.n->n_int;
00458     n->n_bool = e0.n->n_bool + e1.n->n_bool;
00459     n->t = t;
00460     n->l = e0.n; n->l->use++;
00461     n->r = e1.n; n->r->use++;
00462   }
00463 
00464   LinIntExpr::LinIntExpr(const LinIntExpr& e, NodeType t, int c) :
00465     n(new Node) {
00466     n->n_int = e.n->n_int;
00467     n->n_bool = e.n->n_bool;
00468     n->t = t;
00469     n->l = NULL;
00470     n->r = e.n; n->r->use++;
00471     n->c = c;
00472   }
00473 
00474   LinIntExpr::LinIntExpr(int a, const LinIntExpr& e) :
00475     n(new Node) {
00476     n->n_int = e.n->n_int;
00477     n->n_bool = e.n->n_bool;
00478     n->t = NT_MUL;
00479     n->l = e.n; n->l->use++;
00480     n->r = NULL;
00481     n->a = a;
00482   }
00483 
00484   LinIntExpr::LinIntExpr(NonLinIntExpr* e) :
00485     n(new Node) {
00486     n->n_int = 1;
00487     n->n_bool = 0;
00488     n->t = NT_NONLIN;
00489     n->l = n->r = NULL;
00490     n->a = 0;
00491     n->sum.ne = e;
00492   }
00493 
00494   const LinIntExpr&
00495   LinIntExpr::operator =(const LinIntExpr& e) {
00496     if (this != &e) {
00497       if (n->decrement())
00498         delete n;
00499       n = e.n; n->use++;
00500     }
00501     return *this;
00502   }
00503 
00504   LinIntExpr::~LinIntExpr(void) {
00505     if (n->decrement())
00506       delete n;
00507   }
00508 
00509 
00510   void
00511   LinIntExpr::Node::fill(Home home, IntPropLevel ipl,
00512                       Int::Linear::Term<Int::IntView>*& ti,
00513                       Int::Linear::Term<Int::BoolView>*& tb,
00514                       long long int m, long long int& d) const {
00515     switch (this->t) {
00516     case NT_CONST:
00517       Int::Limits::check(m*c,"MiniModel::LinIntExpr");
00518       d += m*c;
00519       break;
00520     case NT_VAR_INT:
00521       Int::Limits::check(m*a,"MiniModel::LinIntExpr");
00522       ti->a=static_cast<int>(m*a); ti->x=x_int; ti++;
00523       break;
00524     case NT_NONLIN:
00525       ti->a=static_cast<int>(m); ti->x=sum.ne->post(home, NULL, ipl); ti++;
00526       break;
00527     case NT_VAR_BOOL:
00528       Int::Limits::check(m*a,"MiniModel::LinIntExpr");
00529       tb->a=static_cast<int>(m*a); tb->x=x_bool; tb++;
00530       break;
00531     case NT_SUM_INT:
00532       for (int i=n_int; i--; ) {
00533         Int::Limits::check(m*sum.ti[i].a,"MiniModel::LinIntExpr");
00534         ti[i].x = sum.ti[i].x; ti[i].a = static_cast<int>(m*sum.ti[i].a);
00535       }
00536       ti += n_int;
00537       break;
00538     case NT_SUM_BOOL:
00539       for (int i=n_bool; i--; ) {
00540         Int::Limits::check(m*sum.tb[i].a,"MiniModel::LinIntExpr");
00541         tb[i].x = sum.tb[i].x; tb[i].a = static_cast<int>(m*sum.tb[i].a);
00542       }
00543       tb += n_bool;
00544       break;
00545     case NT_ADD:
00546       if (l == NULL) {
00547         Int::Limits::check(m*c,"MiniModel::LinIntExpr");
00548         d += m*c;
00549       } else {
00550         l->fill(home,ipl,ti,tb,m,d);
00551       }
00552       r->fill(home,ipl,ti,tb,m,d);
00553       break;
00554     case NT_SUB:
00555       if (l == NULL) {
00556         Int::Limits::check(m*c,"MiniModel::LinIntExpr");
00557         d += m*c;
00558       } else {
00559         l->fill(home,ipl,ti,tb,m,d);
00560       }
00561       r->fill(home,ipl,ti,tb,-m,d);
00562       break;
00563     case NT_MUL:
00564       Int::Limits::check(m*a,"MiniModel::LinIntExpr");
00565       l->fill(home,ipl,ti,tb,m*a,d);
00566       break;
00567     default:
00568       GECODE_NEVER;
00569     }
00570   }
00571 
00572 
00573   /*
00574    * Operators
00575    *
00576    */
00577   LinIntExpr
00578   operator +(int c, const IntVar& x) {
00579     if (x.assigned() &&
00580         Int::Limits::valid(static_cast<long long int>(c)+x.val()))
00581       return LinIntExpr(c+x.val());
00582     else
00583       return LinIntExpr(x,LinIntExpr::NT_ADD,c);
00584   }
00585   LinIntExpr
00586   operator +(int c, const BoolVar& x) {
00587     if (x.assigned() &&
00588         Int::Limits::valid(static_cast<long long int>(c)+x.val()))
00589       return LinIntExpr(c+x.val());
00590     else
00591       return LinIntExpr(x,LinIntExpr::NT_ADD,c);
00592   }
00593   LinIntExpr
00594   operator +(int c, const LinIntExpr& e) {
00595     return LinIntExpr(e,LinIntExpr::NT_ADD,c);
00596   }
00597   LinIntExpr
00598   operator +(const IntVar& x, int c) {
00599     if (x.assigned() &&
00600         Int::Limits::valid(static_cast<long long int>(c)+x.val()))
00601       return LinIntExpr(c+x.val());
00602     else
00603       return LinIntExpr(x,LinIntExpr::NT_ADD,c);
00604   }
00605   LinIntExpr
00606   operator +(const BoolVar& x, int c) {
00607     if (x.assigned() &&
00608         Int::Limits::valid(static_cast<long long int>(c)+x.val()))
00609       return LinIntExpr(c+x.val());
00610     else
00611       return LinIntExpr(x,LinIntExpr::NT_ADD,c);
00612   }
00613   LinIntExpr
00614   operator +(const LinIntExpr& e, int c) {
00615     return LinIntExpr(e,LinIntExpr::NT_ADD,c);
00616   }
00617   LinIntExpr
00618   operator +(const IntVar& x, const IntVar& y) {
00619     if (x.assigned())
00620       return x.val() + y;
00621     else if (y.assigned())
00622       return x + y.val();
00623     else
00624       return LinIntExpr(x,LinIntExpr::NT_ADD,y);
00625   }
00626   LinIntExpr
00627   operator +(const IntVar& x, const BoolVar& y) {
00628     if (x.assigned())
00629       return x.val() + y;
00630     else if (y.assigned())
00631       return x + y.val();
00632     else
00633       return LinIntExpr(x,LinIntExpr::NT_ADD,y);
00634   }
00635   LinIntExpr
00636   operator +(const BoolVar& x, const IntVar& y) {
00637     if (x.assigned())
00638       return x.val() + y;
00639     else if (y.assigned())
00640       return x + y.val();
00641     else
00642       return LinIntExpr(x,LinIntExpr::NT_ADD,y);
00643   }
00644   LinIntExpr
00645   operator +(const BoolVar& x, const BoolVar& y) {
00646     if (x.assigned())
00647       return x.val() + y;
00648     else if (y.assigned())
00649       return x + y.val();
00650     else
00651       return LinIntExpr(x,LinIntExpr::NT_ADD,y);
00652   }
00653   LinIntExpr
00654   operator +(const IntVar& x, const LinIntExpr& e) {
00655     if (x.assigned())
00656       return x.val() + e;
00657     else
00658       return LinIntExpr(x,LinIntExpr::NT_ADD,e);
00659   }
00660   LinIntExpr
00661   operator +(const BoolVar& x, const LinIntExpr& e) {
00662     if (x.assigned())
00663       return x.val() + e;
00664     else
00665       return LinIntExpr(x,LinIntExpr::NT_ADD,e);
00666   }
00667   LinIntExpr
00668   operator +(const LinIntExpr& e, const IntVar& x) {
00669     if (x.assigned())
00670       return e + x.val();
00671     else
00672       return LinIntExpr(e,LinIntExpr::NT_ADD,x);
00673   }
00674   LinIntExpr
00675   operator +(const LinIntExpr& e, const BoolVar& x) {
00676     if (x.assigned())
00677       return e + x.val();
00678     else
00679       return LinIntExpr(e,LinIntExpr::NT_ADD,x);
00680   }
00681   LinIntExpr
00682   operator +(const LinIntExpr& e1, const LinIntExpr& e2) {
00683     return LinIntExpr(e1,LinIntExpr::NT_ADD,e2);
00684   }
00685 
00686   LinIntExpr
00687   operator -(int c, const IntVar& x) {
00688     if (x.assigned() &&
00689         Int::Limits::valid(static_cast<long long int>(c)-x.val()))
00690       return LinIntExpr(c-x.val());
00691     else
00692       return LinIntExpr(x,LinIntExpr::NT_SUB,c);
00693   }
00694   LinIntExpr
00695   operator -(int c, const BoolVar& x) {
00696     if (x.assigned() &&
00697         Int::Limits::valid(static_cast<long long int>(c)-x.val()))
00698       return LinIntExpr(c-x.val());
00699     else
00700       return LinIntExpr(x,LinIntExpr::NT_SUB,c);
00701   }
00702   LinIntExpr
00703   operator -(int c, const LinIntExpr& e) {
00704     return LinIntExpr(e,LinIntExpr::NT_SUB,c);
00705   }
00706   LinIntExpr
00707   operator -(const IntVar& x, int c) {
00708     if (x.assigned() &&
00709         Int::Limits::valid(x.val()-static_cast<long long int>(c)))
00710       return LinIntExpr(x.val()-c);
00711     else
00712       return LinIntExpr(x,LinIntExpr::NT_ADD,-c);
00713   }
00714   LinIntExpr
00715   operator -(const BoolVar& x, int c) {
00716     if (x.assigned() &&
00717         Int::Limits::valid(x.val()-static_cast<long long int>(c)))
00718       return LinIntExpr(x.val()-c);
00719     else
00720       return LinIntExpr(x,LinIntExpr::NT_ADD,-c);
00721   }
00722   LinIntExpr
00723   operator -(const LinIntExpr& e, int c) {
00724     return LinIntExpr(e,LinIntExpr::NT_ADD,-c);
00725   }
00726   LinIntExpr
00727   operator -(const IntVar& x, const IntVar& y) {
00728     if (x.assigned())
00729       return x.val() - y;
00730     else if (y.assigned())
00731       return x - y.val();
00732     else
00733       return LinIntExpr(x,LinIntExpr::NT_SUB,y);
00734   }
00735   LinIntExpr
00736   operator -(const IntVar& x, const BoolVar& y) {
00737     if (x.assigned())
00738       return x.val() - y;
00739     else if (y.assigned())
00740       return x - y.val();
00741     else
00742       return LinIntExpr(x,LinIntExpr::NT_SUB,y);
00743   }
00744   LinIntExpr
00745   operator -(const BoolVar& x, const IntVar& y) {
00746     if (x.assigned())
00747       return x.val() - y;
00748     else if (y.assigned())
00749       return x - y.val();
00750     else
00751       return LinIntExpr(x,LinIntExpr::NT_SUB,y);
00752   }
00753   LinIntExpr
00754   operator -(const BoolVar& x, const BoolVar& y) {
00755     if (x.assigned())
00756       return x.val() - y;
00757     else if (y.assigned())
00758       return x - y.val();
00759     else
00760       return LinIntExpr(x,LinIntExpr::NT_SUB,y);
00761   }
00762   LinIntExpr
00763   operator -(const IntVar& x, const LinIntExpr& e) {
00764     if (x.assigned())
00765       return x.val() - e;
00766     else
00767       return LinIntExpr(x,LinIntExpr::NT_SUB,e);
00768   }
00769   LinIntExpr
00770   operator -(const BoolVar& x, const LinIntExpr& e) {
00771     if (x.assigned())
00772       return x.val() - e;
00773     else
00774       return LinIntExpr(x,LinIntExpr::NT_SUB,e);
00775   }
00776   LinIntExpr
00777   operator -(const LinIntExpr& e, const IntVar& x) {
00778     if (x.assigned())
00779       return e - x.val();
00780     else
00781       return LinIntExpr(e,LinIntExpr::NT_SUB,x);
00782   }
00783   LinIntExpr
00784   operator -(const LinIntExpr& e, const BoolVar& x) {
00785     if (x.assigned())
00786       return e - x.val();
00787     else
00788       return LinIntExpr(e,LinIntExpr::NT_SUB,x);
00789   }
00790   LinIntExpr
00791   operator -(const LinIntExpr& e1, const LinIntExpr& e2) {
00792     return LinIntExpr(e1,LinIntExpr::NT_SUB,e2);
00793   }
00794 
00795   LinIntExpr
00796   operator -(const IntVar& x) {
00797     if (x.assigned())
00798       return LinIntExpr(-x.val());
00799     else
00800       return LinIntExpr(x,LinIntExpr::NT_SUB,0);
00801   }
00802   LinIntExpr
00803   operator -(const BoolVar& x) {
00804     if (x.assigned())
00805       return LinIntExpr(-x.val());
00806     else
00807       return LinIntExpr(x,LinIntExpr::NT_SUB,0);
00808   }
00809   LinIntExpr
00810   operator -(const LinIntExpr& e) {
00811     return LinIntExpr(e,LinIntExpr::NT_SUB,0);
00812   }
00813 
00814   LinIntExpr
00815   operator *(int a, const IntVar& x) {
00816     if (a == 0)
00817       return LinIntExpr(0);
00818     else if (x.assigned() &&
00819              Int::Limits::valid(static_cast<long long int>(a)*x.val()))
00820       return LinIntExpr(a*x.val());
00821     else
00822       return LinIntExpr(x,a);
00823   }
00824   LinIntExpr
00825   operator *(int a, const BoolVar& x) {
00826     if (a == 0)
00827       return LinIntExpr(0);
00828     else if (x.assigned() &&
00829              Int::Limits::valid(static_cast<long long int>(a)*x.val()))
00830       return LinIntExpr(a*x.val());
00831     else
00832       return LinIntExpr(x,a);
00833   }
00834   LinIntExpr
00835   operator *(const IntVar& x, int a) {
00836     if (a == 0)
00837       return LinIntExpr(0);
00838     else if (x.assigned() &&
00839              Int::Limits::valid(static_cast<long long int>(a)*x.val()))
00840       return LinIntExpr(a*x.val());
00841     else
00842       return LinIntExpr(x,a);
00843   }
00844   LinIntExpr
00845   operator *(const BoolVar& x, int a) {
00846     if (a == 0)
00847       return LinIntExpr(0);
00848     else if (x.assigned() &&
00849              Int::Limits::valid(static_cast<long long int>(a)*x.val()))
00850       return LinIntExpr(a*x.val());
00851     else
00852       return LinIntExpr(x,a);
00853   }
00854   LinIntExpr
00855   operator *(const LinIntExpr& e, int a) {
00856     if (a == 0)
00857       return LinIntExpr(0);
00858     else
00859       return LinIntExpr(a,e);
00860   }
00861   LinIntExpr
00862   operator *(int a, const LinIntExpr& e) {
00863     if (a == 0)
00864       return LinIntExpr(0);
00865     else
00866       return LinIntExpr(a,e);
00867   }
00868 
00869   LinIntExpr
00870   sum(const IntVarArgs& x) {
00871     return LinIntExpr(x);
00872   }
00873   LinIntExpr
00874   sum(const IntArgs& a, const IntVarArgs& x) {
00875     return LinIntExpr(a,x);
00876   }
00877   LinIntExpr
00878   sum(const BoolVarArgs& x) {
00879     return LinIntExpr(x);
00880   }
00881   LinIntExpr
00882   sum(const IntArgs& a, const BoolVarArgs& x) {
00883     return LinIntExpr(a,x);
00884   }
00885   LinIntExpr
00886   sum(const Slice<IntArgs>& slice) {
00887     const Slice<IntArgs>::ArgsType & args = slice;
00888     return sum(args);
00889   }
00890   LinIntExpr
00891   sum(const Matrix<IntArgs>& matrix) {
00892     const Matrix<IntArgs>::ArgsType & args = matrix.get_array();
00893     return sum(args);
00894   }
00895   LinIntExpr
00896   sum(const IntArgs& args) {
00897     int i, sum = 0;
00898     const int size = args.size();
00899 
00900     for (i = 0 ; i < size ; ++i)
00901     {
00902       sum += args[i];
00903     }
00904 
00905     return LinIntExpr(sum);
00906   }
00907 
00908 
00909   IntVar
00910   expr(Home home, const LinIntExpr& e, IntPropLevel ipl) {
00911     PostInfo pi(home);
00912     if (!home.failed())
00913       return e.post(home,ipl);
00914     IntVar x(home,Int::Limits::min,Int::Limits::max);
00915     return x;
00916   }
00917 
00918 }
00919 
00920 // STATISTICS: minimodel-any