Generated on Thu Apr 11 13:59:17 2019 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, const IntPropLevels& ipls,
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, const IntPropLevels& ipls,
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 != nullptr) && l->decrement())
00127         delete l;
00128       if ((r != nullptr) && 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, const IntPropLevels& ipls,
00147                       Int::Linear::Term<Int::IntView>* ti,
00148                       Int::Linear::Term<Int::BoolView>* tb) const {
00149     long long int d=0;
00150     fill(home,ipls,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,
00157                    const IntPropLevels& ipls) const {
00158     if (home.failed()) return;
00159     Region r;
00160     if (n->n_bool == 0) {
00161       // Only integer variables
00162       if (n->t==NT_ADD && n->l == nullptr && n->r->t==NT_NONLIN) {
00163         n->r->sum.ne->post(home,irt,-n->c,ipls);
00164       } else if (n->t==NT_SUB && n->r->t==NT_NONLIN && n->l==nullptr) {
00165         switch (irt) {
00166         case IRT_LQ: irt=IRT_GQ; break;
00167         case IRT_LE: irt=IRT_GR; break;
00168         case IRT_GQ: irt=IRT_LQ; break;
00169         case IRT_GR: irt=IRT_LE; break;
00170         default: break;
00171         }
00172         n->r->sum.ne->post(home,irt,n->c,ipls);
00173       } else if (irt==IRT_EQ &&
00174                  n->t==NT_SUB && n->r->t==NT_NONLIN &&
00175                  n->l != nullptr && n->l->t==NT_VAR_INT
00176                  && n->l->a==1) {
00177         (void) n->r->sum.ne->post(home,&n->l->x_int,ipls);
00178       } else if (irt==IRT_EQ &&
00179                  n->t==NT_SUB && n->r->t==NT_VAR_INT &&
00180                  n->l != nullptr && n->l->t==NT_NONLIN
00181                  && n->r->a==1) {
00182         (void) n->l->sum.ne->post(home,&n->r->x_int,ipls);
00183       } else {
00184         Int::Linear::Term<Int::IntView>* its =
00185           r.alloc<Int::Linear::Term<Int::IntView> >(n->n_int);
00186         int c = n->fill(home,ipls,its,nullptr);
00187         Int::Linear::post(home, its, n->n_int, irt, -c,
00188                           (n->n_int > 2) ? ipls.linear() : ipls.linear2());
00189       }
00190     } else if (n->n_int == 0) {
00191       // Only Boolean variables
00192       Int::Linear::Term<Int::BoolView>* bts =
00193         r.alloc<Int::Linear::Term<Int::BoolView> >(n->n_bool);
00194       int c = n->fill(home,ipls,nullptr,bts);
00195       Int::Linear::post(home, bts, n->n_bool, irt, -c,
00196                         (n->n_bool > 2) ? ipls.linear() : ipls.linear2());
00197     } else if (n->n_bool == 1) {
00198       // Integer variables and only one Boolean variable
00199       Int::Linear::Term<Int::IntView>* its =
00200         r.alloc<Int::Linear::Term<Int::IntView> >(n->n_int+1);
00201       Int::Linear::Term<Int::BoolView>* bts =
00202         r.alloc<Int::Linear::Term<Int::BoolView> >(1);
00203       int c = n->fill(home,ipls,its,bts);
00204       IntVar x(home,0,1);
00205       channel(home,bts[0].x,x);
00206       its[n->n_int].x = x;
00207       its[n->n_int].a = bts[0].a;
00208       Int::Linear::post(home, its, n->n_int+1, irt, -c,
00209                         (n->n_int > 1) ? ipls.linear() : ipls.linear2());
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,ipls,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,
00222                         (n->n_bool > 2) ? ipls.linear() : ipls.linear2());
00223       Int::Linear::post(home, its, n->n_int+1, irt, -c,
00224                         (n->n_int > 1) ? ipls.linear() : ipls.linear2());
00225     }
00226   }
00227 
00228   void
00229   LinIntExpr::post(Home home, IntRelType irt, const BoolVar& b,
00230                    const IntPropLevels& ipls) const {
00231     if (home.failed()) return;
00232     Region r;
00233     if (n->n_bool == 0) {
00234       // Only integer variables
00235       if (n->t==NT_ADD && n->l==nullptr && n->r->t==NT_NONLIN) {
00236         n->r->sum.ne->post(home,irt,-n->c,b,ipls);
00237       } else if (n->t==NT_SUB && n->l==nullptr && n->r->t==NT_NONLIN) {
00238         switch (irt) {
00239         case IRT_LQ: irt=IRT_GQ; break;
00240         case IRT_LE: irt=IRT_GR; break;
00241         case IRT_GQ: irt=IRT_LQ; break;
00242         case IRT_GR: irt=IRT_LE; break;
00243         default: break;
00244         }
00245         n->r->sum.ne->post(home,irt,n->c,b,ipls);
00246       } else {
00247         Int::Linear::Term<Int::IntView>* its =
00248           r.alloc<Int::Linear::Term<Int::IntView> >(n->n_int);
00249         int c = n->fill(home,ipls,its,nullptr);
00250         Int::Linear::post(home, its, n->n_int, irt, -c, b,
00251                           (n->n_int > 2) ? ipls.linear() : ipls.linear2());
00252       }
00253     } else if (n->n_int == 0) {
00254       // Only Boolean variables
00255       Int::Linear::Term<Int::BoolView>* bts =
00256         r.alloc<Int::Linear::Term<Int::BoolView> >(n->n_bool);
00257       int c = n->fill(home,ipls,nullptr,bts);
00258       Int::Linear::post(home, bts, n->n_bool, irt, -c, b,
00259                         (n->n_bool > 2) ? ipls.linear() : ipls.linear2());
00260     } else if (n->n_bool == 1) {
00261       // Integer variables and only one Boolean variable
00262       Int::Linear::Term<Int::IntView>* its =
00263         r.alloc<Int::Linear::Term<Int::IntView> >(n->n_int+1);
00264       Int::Linear::Term<Int::BoolView>* bts =
00265         r.alloc<Int::Linear::Term<Int::BoolView> >(1);
00266       int c = n->fill(home,ipls,its,bts);
00267       IntVar x(home,0,1);
00268       channel(home,bts[0].x,x);
00269       its[n->n_int].x = x;
00270       its[n->n_int].a = bts[0].a;
00271       Int::Linear::post(home, its, n->n_int+1, irt, -c, b,
00272                         (n->n_int > 1) ? ipls.linear() : ipls.linear2());
00273     } else {
00274       // Both integer and Boolean variables
00275       Int::Linear::Term<Int::IntView>* its =
00276         r.alloc<Int::Linear::Term<Int::IntView> >(n->n_int+1);
00277       Int::Linear::Term<Int::BoolView>* bts =
00278         r.alloc<Int::Linear::Term<Int::BoolView> >(n->n_bool);
00279       int c = n->fill(home,ipls,its,bts);
00280       int min, max;
00281       Int::Linear::estimate(&bts[0],n->n_bool,0,min,max);
00282       IntVar x(home,min,max);
00283       its[n->n_int].x = x; its[n->n_int].a = 1;
00284       Int::Linear::post(home, bts, n->n_bool, IRT_EQ, x, 0,
00285                         (n->n_int > 1) ? ipls.linear() : ipls.linear2());
00286       Int::Linear::post(home, its, n->n_int+1, irt, -c, b,
00287                         (n->n_bool > 2) ? ipls.linear() : ipls.linear2());
00288     }
00289   }
00290 
00291   IntVar
00292   LinIntExpr::post(Home home, const IntPropLevels& ipls) const {
00293     if (home.failed()) return IntVar(home,0,0);
00294     Region r;
00295     if (n->n_bool == 0) {
00296       // Only integer variables
00297       Int::Linear::Term<Int::IntView>* its =
00298         r.alloc<Int::Linear::Term<Int::IntView> >(n->n_int+1);
00299       int c = n->fill(home,ipls,its,nullptr);
00300       if ((n->n_int == 1) && (c == 0) && (its[0].a == 1))
00301         return its[0].x;
00302       int min, max;
00303       Int::Linear::estimate(&its[0],n->n_int,c,min,max);
00304       IntVar x(home, min, max);
00305       its[n->n_int].x = x; its[n->n_int].a = -1;
00306       Int::Linear::post(home, its, n->n_int+1, IRT_EQ, -c,
00307                         (n->n_int > 1) ? ipls.linear() : ipls.linear2());
00308       return x;
00309     } else if (n->n_int == 0) {
00310       // Only Boolean variables
00311       Int::Linear::Term<Int::BoolView>* bts =
00312         r.alloc<Int::Linear::Term<Int::BoolView> >(n->n_bool);
00313       int c = n->fill(home,ipls,nullptr,bts);
00314       int min, max;
00315       Int::Linear::estimate(&bts[0],n->n_bool,c,min,max);
00316       IntVar x(home, min, max);
00317       Int::Linear::post(home, bts, n->n_bool, IRT_EQ, x, -c,
00318                         (n->n_bool > 2) ? ipls.linear() : ipls.linear2());
00319       return x;
00320     } else if (n->n_bool == 1) {
00321       // Integer variables and single Boolean variable
00322       Int::Linear::Term<Int::IntView>* its =
00323         r.alloc<Int::Linear::Term<Int::IntView> >(n->n_int+2);
00324       Int::Linear::Term<Int::BoolView>* bts =
00325         r.alloc<Int::Linear::Term<Int::BoolView> >(1);
00326       int c = n->fill(home,ipls,its,bts);
00327       IntVar x(home, 0, 1);
00328       channel(home, x, bts[0].x);
00329       its[n->n_int].x = x; its[n->n_int].a = bts[0].a;
00330       int y_min, y_max;
00331       Int::Linear::estimate(&its[0],n->n_int+1,c,y_min,y_max);
00332       IntVar y(home, y_min, y_max);
00333       its[n->n_int+1].x = y; its[n->n_int+1].a = -1;
00334       Int::Linear::post(home, its, n->n_int+2, IRT_EQ, -c, ipls.linear());
00335       return y;
00336     } else {
00337       // Both integer and Boolean variables
00338       Int::Linear::Term<Int::IntView>* its =
00339         r.alloc<Int::Linear::Term<Int::IntView> >(n->n_int+2);
00340       Int::Linear::Term<Int::BoolView>* bts =
00341         r.alloc<Int::Linear::Term<Int::BoolView> >(n->n_bool);
00342       int c = n->fill(home,ipls,its,bts);
00343       int x_min, x_max;
00344       Int::Linear::estimate(&bts[0],n->n_bool,0,x_min,x_max);
00345       IntVar x(home, x_min, x_max);
00346       Int::Linear::post(home, bts, n->n_bool, IRT_EQ, x, 0,
00347                         (n->n_bool > 2) ? ipls.linear() : ipls.linear2());
00348       its[n->n_int].x = x; its[n->n_int].a = 1;
00349       int y_min, y_max;
00350       Int::Linear::estimate(&its[0],n->n_int+1,c,y_min,y_max);
00351       IntVar y(home, y_min, y_max);
00352       its[n->n_int+1].x = y; its[n->n_int+1].a = -1;
00353       Int::Linear::post(home, its, n->n_int+2, IRT_EQ, -c, ipls.linear());
00354       return y;
00355     }
00356   }
00357 
00358   NonLinIntExpr*
00359   LinIntExpr::nle(void) const {
00360     return n->t == NT_NONLIN ? n->sum.ne : nullptr;
00361   }
00362 
00363   LinIntExpr::LinIntExpr(void) :
00364     n(new Node) {
00365     n->n_int = n->n_bool = 0;
00366     n->t = NT_VAR_INT;
00367     n->l = n->r = nullptr;
00368     n->a = 0;
00369   }
00370 
00371   LinIntExpr::LinIntExpr(int c) :
00372     n(new Node) {
00373     n->n_int = n->n_bool = 0;
00374     n->t = NT_CONST;
00375     n->l = n->r = nullptr;
00376     n->a = 0;
00377     Int::Limits::check(c,"MiniModel::LinIntExpr");
00378     n->c = c;
00379   }
00380 
00381   LinIntExpr::LinIntExpr(const IntVar& x, int a) :
00382     n(new Node) {
00383     n->n_int = 1;
00384     n->n_bool = 0;
00385     n->t = NT_VAR_INT;
00386     n->l = n->r = nullptr;
00387     n->a = a;
00388     n->x_int = x;
00389   }
00390 
00391   LinIntExpr::LinIntExpr(const BoolVar& x, int a) :
00392     n(new Node) {
00393     n->n_int = 0;
00394     n->n_bool = 1;
00395     n->t = NT_VAR_BOOL;
00396     n->l = n->r = nullptr;
00397     n->a = a;
00398     n->x_bool = x;
00399   }
00400 
00401   LinIntExpr::LinIntExpr(const IntVarArgs& x) :
00402     n(new Node) {
00403     n->n_int = x.size();
00404     n->n_bool = 0;
00405     n->t = NT_SUM_INT;
00406     n->l = n->r = nullptr;
00407     if (x.size() > 0) {
00408       n->sum.ti = heap.alloc<Int::Linear::Term<Int::IntView> >(x.size());
00409       for (int i=x.size(); i--; ) {
00410         n->sum.ti[i].x = x[i];
00411         n->sum.ti[i].a = 1;
00412       }
00413     }
00414   }
00415 
00416   LinIntExpr::LinIntExpr(const IntArgs& a, const IntVarArgs& x) :
00417     n(new Node) {
00418     if (a.size() != x.size())
00419       throw Int::ArgumentSizeMismatch("MiniModel::LinIntExpr");
00420     n->n_int = x.size();
00421     n->n_bool = 0;
00422     n->t = NT_SUM_INT;
00423     n->l = n->r = nullptr;
00424     if (x.size() > 0) {
00425       n->sum.ti = heap.alloc<Int::Linear::Term<Int::IntView> >(x.size());
00426       for (int i=x.size(); i--; ) {
00427         n->sum.ti[i].x = x[i];
00428         n->sum.ti[i].a = a[i];
00429       }
00430     }
00431   }
00432 
00433   LinIntExpr::LinIntExpr(const BoolVarArgs& x) :
00434     n(new Node) {
00435     n->n_int = 0;
00436     n->n_bool = x.size();
00437     n->t = NT_SUM_BOOL;
00438     n->l = n->r = nullptr;
00439     if (x.size() > 0) {
00440       n->sum.tb = heap.alloc<Int::Linear::Term<Int::BoolView> >(x.size());
00441       for (int i=x.size(); i--; ) {
00442         n->sum.tb[i].x = x[i];
00443         n->sum.tb[i].a = 1;
00444       }
00445     }
00446   }
00447 
00448   LinIntExpr::LinIntExpr(const IntArgs& a, const BoolVarArgs& x) :
00449     n(new Node) {
00450     if (a.size() != x.size())
00451       throw Int::ArgumentSizeMismatch("MiniModel::LinIntExpr");
00452     n->n_int = 0;
00453     n->n_bool = x.size();
00454     n->t = NT_SUM_BOOL;
00455     n->l = n->r = nullptr;
00456     if (x.size() > 0) {
00457       n->sum.tb = heap.alloc<Int::Linear::Term<Int::BoolView> >(x.size());
00458       for (int i=x.size(); i--; ) {
00459         n->sum.tb[i].x = x[i];
00460         n->sum.tb[i].a = a[i];
00461       }
00462     }
00463   }
00464 
00465   LinIntExpr::LinIntExpr(const LinIntExpr& e0, NodeType t, const LinIntExpr& e1) :
00466     n(new Node) {
00467     n->n_int = e0.n->n_int + e1.n->n_int;
00468     n->n_bool = e0.n->n_bool + e1.n->n_bool;
00469     n->t = t;
00470     n->l = e0.n; n->l->use++;
00471     n->r = e1.n; n->r->use++;
00472   }
00473 
00474   LinIntExpr::LinIntExpr(const LinIntExpr& e, NodeType t, int c) :
00475     n(new Node) {
00476     n->n_int = e.n->n_int;
00477     n->n_bool = e.n->n_bool;
00478     n->t = t;
00479     n->l = nullptr;
00480     n->r = e.n; n->r->use++;
00481     n->c = c;
00482   }
00483 
00484   LinIntExpr::LinIntExpr(int a, const LinIntExpr& e) :
00485     n(new Node) {
00486     n->n_int = e.n->n_int;
00487     n->n_bool = e.n->n_bool;
00488     n->t = NT_MUL;
00489     n->l = e.n; n->l->use++;
00490     n->r = nullptr;
00491     n->a = a;
00492   }
00493 
00494   LinIntExpr::LinIntExpr(NonLinIntExpr* e) :
00495     n(new Node) {
00496     n->n_int = 1;
00497     n->n_bool = 0;
00498     n->t = NT_NONLIN;
00499     n->l = n->r = nullptr;
00500     n->a = 0;
00501     n->sum.ne = e;
00502   }
00503 
00504   const LinIntExpr&
00505   LinIntExpr::operator =(const LinIntExpr& e) {
00506     if (this != &e) {
00507       if (n->decrement())
00508         delete n;
00509       n = e.n; n->use++;
00510     }
00511     return *this;
00512   }
00513 
00514   LinIntExpr::~LinIntExpr(void) {
00515     if (n->decrement())
00516       delete n;
00517   }
00518 
00519 
00520   void
00521   LinIntExpr::Node::fill(Home home, const IntPropLevels& ipls,
00522                          Int::Linear::Term<Int::IntView>*& ti,
00523                          Int::Linear::Term<Int::BoolView>*& tb,
00524                          long long int m, long long int& d) const {
00525     switch (this->t) {
00526     case NT_CONST:
00527       Int::Limits::check(m*c,"MiniModel::LinIntExpr");
00528       d += m*c;
00529       break;
00530     case NT_VAR_INT:
00531       Int::Limits::check(m*a,"MiniModel::LinIntExpr");
00532       ti->a=static_cast<int>(m*a); ti->x=x_int; ti++;
00533       break;
00534     case NT_NONLIN:
00535       ti->a=static_cast<int>(m); ti->x=sum.ne->post(home, nullptr, ipls); ti++;
00536       break;
00537     case NT_VAR_BOOL:
00538       Int::Limits::check(m*a,"MiniModel::LinIntExpr");
00539       tb->a=static_cast<int>(m*a); tb->x=x_bool; tb++;
00540       break;
00541     case NT_SUM_INT:
00542       for (int i=n_int; i--; ) {
00543         Int::Limits::check(m*sum.ti[i].a,"MiniModel::LinIntExpr");
00544         ti[i].x = sum.ti[i].x; ti[i].a = static_cast<int>(m*sum.ti[i].a);
00545       }
00546       ti += n_int;
00547       break;
00548     case NT_SUM_BOOL:
00549       for (int i=n_bool; i--; ) {
00550         Int::Limits::check(m*sum.tb[i].a,"MiniModel::LinIntExpr");
00551         tb[i].x = sum.tb[i].x; tb[i].a = static_cast<int>(m*sum.tb[i].a);
00552       }
00553       tb += n_bool;
00554       break;
00555     case NT_ADD:
00556       if (l == nullptr) {
00557         Int::Limits::check(m*c,"MiniModel::LinIntExpr");
00558         d += m*c;
00559       } else {
00560         l->fill(home,ipls,ti,tb,m,d);
00561       }
00562       r->fill(home,ipls,ti,tb,m,d);
00563       break;
00564     case NT_SUB:
00565       if (l == nullptr) {
00566         Int::Limits::check(m*c,"MiniModel::LinIntExpr");
00567         d += m*c;
00568       } else {
00569         l->fill(home,ipls,ti,tb,m,d);
00570       }
00571       r->fill(home,ipls,ti,tb,-m,d);
00572       break;
00573     case NT_MUL:
00574       Int::Limits::check(m*a,"MiniModel::LinIntExpr");
00575       l->fill(home,ipls,ti,tb,m*a,d);
00576       break;
00577     default:
00578       GECODE_NEVER;
00579     }
00580   }
00581 
00582 
00583   /*
00584    * Operators
00585    *
00586    */
00587   LinIntExpr
00588   operator +(int c, const IntVar& x) {
00589     if (x.assigned() &&
00590         Int::Limits::valid(static_cast<long long int>(c)+x.val()))
00591       return LinIntExpr(c+x.val());
00592     else
00593       return LinIntExpr(x,LinIntExpr::NT_ADD,c);
00594   }
00595   LinIntExpr
00596   operator +(int c, const BoolVar& x) {
00597     if (x.assigned() &&
00598         Int::Limits::valid(static_cast<long long int>(c)+x.val()))
00599       return LinIntExpr(c+x.val());
00600     else
00601       return LinIntExpr(x,LinIntExpr::NT_ADD,c);
00602   }
00603   LinIntExpr
00604   operator +(int c, const LinIntExpr& e) {
00605     return LinIntExpr(e,LinIntExpr::NT_ADD,c);
00606   }
00607   LinIntExpr
00608   operator +(const IntVar& x, int c) {
00609     if (x.assigned() &&
00610         Int::Limits::valid(static_cast<long long int>(c)+x.val()))
00611       return LinIntExpr(c+x.val());
00612     else
00613       return LinIntExpr(x,LinIntExpr::NT_ADD,c);
00614   }
00615   LinIntExpr
00616   operator +(const BoolVar& x, int c) {
00617     if (x.assigned() &&
00618         Int::Limits::valid(static_cast<long long int>(c)+x.val()))
00619       return LinIntExpr(c+x.val());
00620     else
00621       return LinIntExpr(x,LinIntExpr::NT_ADD,c);
00622   }
00623   LinIntExpr
00624   operator +(const LinIntExpr& e, int c) {
00625     return LinIntExpr(e,LinIntExpr::NT_ADD,c);
00626   }
00627   LinIntExpr
00628   operator +(const IntVar& x, const IntVar& y) {
00629     if (x.assigned())
00630       return x.val() + y;
00631     else if (y.assigned())
00632       return x + y.val();
00633     else
00634       return LinIntExpr(x,LinIntExpr::NT_ADD,y);
00635   }
00636   LinIntExpr
00637   operator +(const IntVar& x, const BoolVar& y) {
00638     if (x.assigned())
00639       return x.val() + y;
00640     else if (y.assigned())
00641       return x + y.val();
00642     else
00643       return LinIntExpr(x,LinIntExpr::NT_ADD,y);
00644   }
00645   LinIntExpr
00646   operator +(const BoolVar& x, const IntVar& y) {
00647     if (x.assigned())
00648       return x.val() + y;
00649     else if (y.assigned())
00650       return x + y.val();
00651     else
00652       return LinIntExpr(x,LinIntExpr::NT_ADD,y);
00653   }
00654   LinIntExpr
00655   operator +(const BoolVar& x, const BoolVar& y) {
00656     if (x.assigned())
00657       return x.val() + y;
00658     else if (y.assigned())
00659       return x + y.val();
00660     else
00661       return LinIntExpr(x,LinIntExpr::NT_ADD,y);
00662   }
00663   LinIntExpr
00664   operator +(const IntVar& x, const LinIntExpr& e) {
00665     if (x.assigned())
00666       return x.val() + e;
00667     else
00668       return LinIntExpr(x,LinIntExpr::NT_ADD,e);
00669   }
00670   LinIntExpr
00671   operator +(const BoolVar& x, const LinIntExpr& e) {
00672     if (x.assigned())
00673       return x.val() + e;
00674     else
00675       return LinIntExpr(x,LinIntExpr::NT_ADD,e);
00676   }
00677   LinIntExpr
00678   operator +(const LinIntExpr& e, const IntVar& x) {
00679     if (x.assigned())
00680       return e + x.val();
00681     else
00682       return LinIntExpr(e,LinIntExpr::NT_ADD,x);
00683   }
00684   LinIntExpr
00685   operator +(const LinIntExpr& e, const BoolVar& x) {
00686     if (x.assigned())
00687       return e + x.val();
00688     else
00689       return LinIntExpr(e,LinIntExpr::NT_ADD,x);
00690   }
00691   LinIntExpr
00692   operator +(const LinIntExpr& e1, const LinIntExpr& e2) {
00693     return LinIntExpr(e1,LinIntExpr::NT_ADD,e2);
00694   }
00695 
00696   LinIntExpr
00697   operator -(int c, const IntVar& x) {
00698     if (x.assigned() &&
00699         Int::Limits::valid(static_cast<long long int>(c)-x.val()))
00700       return LinIntExpr(c-x.val());
00701     else
00702       return LinIntExpr(x,LinIntExpr::NT_SUB,c);
00703   }
00704   LinIntExpr
00705   operator -(int c, const BoolVar& x) {
00706     if (x.assigned() &&
00707         Int::Limits::valid(static_cast<long long int>(c)-x.val()))
00708       return LinIntExpr(c-x.val());
00709     else
00710       return LinIntExpr(x,LinIntExpr::NT_SUB,c);
00711   }
00712   LinIntExpr
00713   operator -(int c, const LinIntExpr& e) {
00714     return LinIntExpr(e,LinIntExpr::NT_SUB,c);
00715   }
00716   LinIntExpr
00717   operator -(const IntVar& x, int c) {
00718     if (x.assigned() &&
00719         Int::Limits::valid(x.val()-static_cast<long long int>(c)))
00720       return LinIntExpr(x.val()-c);
00721     else
00722       return LinIntExpr(x,LinIntExpr::NT_ADD,-c);
00723   }
00724   LinIntExpr
00725   operator -(const BoolVar& x, int c) {
00726     if (x.assigned() &&
00727         Int::Limits::valid(x.val()-static_cast<long long int>(c)))
00728       return LinIntExpr(x.val()-c);
00729     else
00730       return LinIntExpr(x,LinIntExpr::NT_ADD,-c);
00731   }
00732   LinIntExpr
00733   operator -(const LinIntExpr& e, int c) {
00734     return LinIntExpr(e,LinIntExpr::NT_ADD,-c);
00735   }
00736   LinIntExpr
00737   operator -(const IntVar& x, const IntVar& y) {
00738     if (x.assigned())
00739       return x.val() - y;
00740     else if (y.assigned())
00741       return x - y.val();
00742     else
00743       return LinIntExpr(x,LinIntExpr::NT_SUB,y);
00744   }
00745   LinIntExpr
00746   operator -(const IntVar& x, const BoolVar& y) {
00747     if (x.assigned())
00748       return x.val() - y;
00749     else if (y.assigned())
00750       return x - y.val();
00751     else
00752       return LinIntExpr(x,LinIntExpr::NT_SUB,y);
00753   }
00754   LinIntExpr
00755   operator -(const BoolVar& x, const IntVar& y) {
00756     if (x.assigned())
00757       return x.val() - y;
00758     else if (y.assigned())
00759       return x - y.val();
00760     else
00761       return LinIntExpr(x,LinIntExpr::NT_SUB,y);
00762   }
00763   LinIntExpr
00764   operator -(const BoolVar& x, const BoolVar& y) {
00765     if (x.assigned())
00766       return x.val() - y;
00767     else if (y.assigned())
00768       return x - y.val();
00769     else
00770       return LinIntExpr(x,LinIntExpr::NT_SUB,y);
00771   }
00772   LinIntExpr
00773   operator -(const IntVar& x, const LinIntExpr& e) {
00774     if (x.assigned())
00775       return x.val() - e;
00776     else
00777       return LinIntExpr(x,LinIntExpr::NT_SUB,e);
00778   }
00779   LinIntExpr
00780   operator -(const BoolVar& x, const LinIntExpr& e) {
00781     if (x.assigned())
00782       return x.val() - e;
00783     else
00784       return LinIntExpr(x,LinIntExpr::NT_SUB,e);
00785   }
00786   LinIntExpr
00787   operator -(const LinIntExpr& e, const IntVar& x) {
00788     if (x.assigned())
00789       return e - x.val();
00790     else
00791       return LinIntExpr(e,LinIntExpr::NT_SUB,x);
00792   }
00793   LinIntExpr
00794   operator -(const LinIntExpr& e, const BoolVar& x) {
00795     if (x.assigned())
00796       return e - x.val();
00797     else
00798       return LinIntExpr(e,LinIntExpr::NT_SUB,x);
00799   }
00800   LinIntExpr
00801   operator -(const LinIntExpr& e1, const LinIntExpr& e2) {
00802     return LinIntExpr(e1,LinIntExpr::NT_SUB,e2);
00803   }
00804 
00805   LinIntExpr
00806   operator -(const IntVar& x) {
00807     if (x.assigned())
00808       return LinIntExpr(-x.val());
00809     else
00810       return LinIntExpr(x,LinIntExpr::NT_SUB,0);
00811   }
00812   LinIntExpr
00813   operator -(const BoolVar& x) {
00814     if (x.assigned())
00815       return LinIntExpr(-x.val());
00816     else
00817       return LinIntExpr(x,LinIntExpr::NT_SUB,0);
00818   }
00819   LinIntExpr
00820   operator -(const LinIntExpr& e) {
00821     return LinIntExpr(e,LinIntExpr::NT_SUB,0);
00822   }
00823 
00824   LinIntExpr
00825   operator *(int a, const IntVar& 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 *(int a, const BoolVar& x) {
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 IntVar& 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 BoolVar& x, int a) {
00856     if (a == 0)
00857       return LinIntExpr(0);
00858     else if (x.assigned() &&
00859              Int::Limits::valid(static_cast<long long int>(a)*x.val()))
00860       return LinIntExpr(a*x.val());
00861     else
00862       return LinIntExpr(x,a);
00863   }
00864   LinIntExpr
00865   operator *(const LinIntExpr& e, int a) {
00866     if (a == 0)
00867       return LinIntExpr(0);
00868     else
00869       return LinIntExpr(a,e);
00870   }
00871   LinIntExpr
00872   operator *(int a, const LinIntExpr& e) {
00873     if (a == 0)
00874       return LinIntExpr(0);
00875     else
00876       return LinIntExpr(a,e);
00877   }
00878 
00879   LinIntExpr
00880   sum(const IntVarArgs& x) {
00881     return LinIntExpr(x);
00882   }
00883   LinIntExpr
00884   sum(const IntArgs& a, const IntVarArgs& x) {
00885     return LinIntExpr(a,x);
00886   }
00887   LinIntExpr
00888   sum(const BoolVarArgs& x) {
00889     return LinIntExpr(x);
00890   }
00891   LinIntExpr
00892   sum(const IntArgs& a, const BoolVarArgs& x) {
00893     return LinIntExpr(a,x);
00894   }
00895   LinIntExpr
00896   sum(const Slice<IntArgs>& slice) {
00897     const Slice<IntArgs>::ArgsType & args = slice;
00898     return sum(args);
00899   }
00900   LinIntExpr
00901   sum(const Matrix<IntArgs>& matrix) {
00902     const Matrix<IntArgs>::ArgsType & args = matrix.get_array();
00903     return sum(args);
00904   }
00905   LinIntExpr
00906   sum(const IntArgs& args) {
00907     int sum = 0;
00908     for (int i = 0; i<args.size(); i++)
00909       sum += args[i];
00910     return LinIntExpr(sum);
00911   }
00912 
00913 
00914   IntVar
00915   expr(Home home, const LinIntExpr& e, const IntPropLevels& ipls) {
00916     PostInfo pi(home);
00917     if (!home.failed())
00918       return e.post(home,ipls);
00919     IntVar x(home,Int::Limits::min,Int::Limits::max);
00920     return x;
00921   }
00922 
00923 }
00924 
00925 // STATISTICS: minimodel-any