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