Generated on Fri Mar 20 15:56:11 2015 for Gecode by doxygen 1.6.3

bool-post.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  *     Tias Guns <tias.guns@cs.kuleuven.be>
00006  *
00007  *  Copyright:
00008  *     Christian Schulte, 2002
00009  *     Tias Guns, 2009
00010  *
00011  *  Last modified:
00012  *     $Date: 2013-02-14 16:29:11 +0100 (Thu, 14 Feb 2013) $ by $Author: schulte $
00013  *     $Revision: 13292 $
00014  *
00015  *  This file is part of Gecode, the generic constraint
00016  *  development environment:
00017  *     http://www.gecode.org
00018  *
00019  *  Permission is hereby granted, free of charge, to any person obtaining
00020  *  a copy of this software and associated documentation files (the
00021  *  "Software"), to deal in the Software without restriction, including
00022  *  without limitation the rights to use, copy, modify, merge, publish,
00023  *  distribute, sublicense, and/or sell copies of the Software, and to
00024  *  permit persons to whom the Software is furnished to do so, subject to
00025  *  the following conditions:
00026  *
00027  *  The above copyright notice and this permission notice shall be
00028  *  included in all copies or substantial portions of the Software.
00029  *
00030  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00031  *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00032  *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00033  *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
00034  *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
00035  *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
00036  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00037  *
00038  */
00039 
00040 #include <gecode/int/linear.hh>
00041 #include <gecode/int/div.hh>
00042 
00043 namespace Gecode { namespace Int { namespace Linear {
00044 
00046   forceinline IntRelType 
00047   inverse(const IntRelType irt) {
00048     switch (irt) {
00049       case IRT_EQ: return IRT_NQ; break;
00050       case IRT_NQ: return IRT_EQ; break;
00051       case IRT_GQ: return IRT_LE; break;
00052       case IRT_LQ: return IRT_GR; break;
00053       case IRT_LE: return IRT_GQ; break;
00054       case IRT_GR: return IRT_LQ; break;
00055       default: GECODE_NEVER;
00056     }
00057     return IRT_EQ; // Avoid compiler warnings
00058   }
00059 
00061   forceinline void
00062   eliminate(Term<BoolView>* t, int &n, long long int& d) {
00063     for (int i=n; i--; )
00064       if (t[i].x.one()) {
00065         d -= t[i].a; t[i]=t[--n];
00066       } else if (t[i].x.zero()) {
00067         t[i]=t[--n];
00068       }
00069     Limits::check(d,"Int::linear");
00070   }
00071 
00073   forceinline void
00074   rewrite(IntRelType &r, long long int &d) {
00075       switch (r) {
00076       case IRT_EQ: case IRT_NQ: case IRT_LQ: case IRT_GQ:
00077         break;
00078       case IRT_LE:
00079         d--; r = IRT_LQ; break;
00080       case IRT_GR:
00081         d++; r = IRT_GQ; break;
00082       default:
00083         throw UnknownRelation("Int::linear");
00084       }
00085   }
00086 
00087   forceinline void
00088   post_pos_unit(Home home,
00089                 Term<BoolView>* t_p, int n_p,
00090                 IntRelType irt, IntView y, int c) {
00091     switch (irt) {
00092     case IRT_EQ:
00093       {
00094         ViewArray<BoolView> x(home,n_p);
00095         for (int i=n_p; i--; )
00096           x[i]=t_p[i].x;
00097         GECODE_ES_FAIL((EqBoolView<BoolView,IntView>
00098                              ::post(home,x,y,c)));
00099       }
00100       break;
00101     case IRT_NQ:
00102       {
00103         ViewArray<BoolView> x(home,n_p);
00104         for (int i=n_p; i--; )
00105           x[i]=t_p[i].x;
00106         GECODE_ES_FAIL((NqBoolView<BoolView,IntView>
00107                              ::post(home,x,y,c)));
00108       }
00109       break;
00110     case IRT_GQ:
00111       {
00112         ViewArray<BoolView> x(home,n_p);
00113         for (int i=n_p; i--; )
00114           x[i]=t_p[i].x;
00115         GECODE_ES_FAIL((GqBoolView<BoolView,IntView>
00116                              ::post(home,x,y,c)));
00117       }
00118       break;
00119     case IRT_LQ:
00120       {
00121         ViewArray<NegBoolView> x(home,n_p);
00122         for (int i=n_p; i--; )
00123           x[i]=NegBoolView(t_p[i].x);
00124         MinusView z(y);
00125         GECODE_ES_FAIL((GqBoolView<NegBoolView,MinusView>
00126                              ::post(home,x,z,n_p-c)));
00127       }
00128       break;
00129     default: GECODE_NEVER;
00130     }
00131   }
00132 
00133   forceinline void
00134   post_pos_unit(Home home,
00135                 Term<BoolView>* t_p, int n_p,
00136                 IntRelType irt, ZeroIntView, int c) {
00137     switch (irt) {
00138     case IRT_EQ:
00139       {
00140         ViewArray<BoolView> x(home,n_p);
00141         for (int i=n_p; i--; )
00142           x[i]=t_p[i].x;
00143         GECODE_ES_FAIL((EqBoolInt<BoolView>::post(home,x,c)));
00144       }
00145       break;
00146     case IRT_NQ:
00147       {
00148         ViewArray<BoolView> x(home,n_p);
00149         for (int i=n_p; i--; )
00150           x[i]=t_p[i].x;
00151         GECODE_ES_FAIL((NqBoolInt<BoolView>::post(home,x,c)));
00152       }
00153       break;
00154     case IRT_GQ:
00155       {
00156         ViewArray<BoolView> x(home,n_p);
00157         for (int i=n_p; i--; )
00158           x[i]=t_p[i].x;
00159         GECODE_ES_FAIL((GqBoolInt<BoolView>::post(home,x,c)));
00160       }
00161       break;
00162     case IRT_LQ:
00163       {
00164         ViewArray<NegBoolView> x(home,n_p);
00165         for (int i=n_p; i--; )
00166           x[i]=NegBoolView(t_p[i].x);
00167         GECODE_ES_FAIL((GqBoolInt<NegBoolView>::post(home,x,n_p-c)));
00168       }
00169       break;
00170     default: GECODE_NEVER;
00171     }
00172   }
00173 
00174   forceinline void
00175   post_pos_unit(Home home,
00176                 Term<BoolView>* t_p, int n_p,
00177                 IntRelType irt, int c, Reify r,
00178                 IntConLevel) {
00179     switch (irt) {
00180     case IRT_EQ:
00181       {
00182         ViewArray<BoolView> x(home,n_p);
00183         for (int i=n_p; i--; )
00184           x[i]=t_p[i].x;
00185         switch (r.mode()) {
00186         case RM_EQV:
00187           GECODE_ES_FAIL((ReEqBoolInt<BoolView,BoolView,RM_EQV>::
00188                           post(home,x,c,r.var())));
00189           break;
00190         case RM_IMP:
00191           GECODE_ES_FAIL((ReEqBoolInt<BoolView,BoolView,RM_IMP>::
00192                           post(home,x,c,r.var())));
00193           break;
00194         case RM_PMI:
00195           GECODE_ES_FAIL((ReEqBoolInt<BoolView,BoolView,RM_PMI>::
00196                           post(home,x,c,r.var())));
00197           break;
00198         default: GECODE_NEVER;
00199         }
00200       }
00201       break;
00202     case IRT_NQ:
00203       {
00204         ViewArray<BoolView> x(home,n_p);
00205         for (int i=n_p; i--; )
00206           x[i]=t_p[i].x;
00207         NegBoolView nb(r.var());
00208         switch (r.mode()) {
00209         case RM_EQV:
00210           GECODE_ES_FAIL((ReEqBoolInt<BoolView,NegBoolView,RM_EQV>::
00211                           post(home,x,c,nb)));
00212           break;
00213         case RM_IMP:
00214           GECODE_ES_FAIL((ReEqBoolInt<BoolView,NegBoolView,RM_PMI>::
00215                           post(home,x,c,nb)));
00216           break;
00217         case RM_PMI:
00218           GECODE_ES_FAIL((ReEqBoolInt<BoolView,NegBoolView,RM_IMP>::
00219                           post(home,x,c,nb)));
00220           break;
00221         default: GECODE_NEVER;
00222         }
00223       }
00224       break;
00225     case IRT_GQ:
00226       {
00227         ViewArray<BoolView> x(home,n_p);
00228         for (int i=n_p; i--; )
00229           x[i]=t_p[i].x;
00230         switch (r.mode()) {
00231         case RM_EQV:
00232           GECODE_ES_FAIL((ReGqBoolInt<BoolView,BoolView,RM_EQV>::
00233                           post(home,x,c,r.var())));
00234           break;
00235         case RM_IMP:
00236           GECODE_ES_FAIL((ReGqBoolInt<BoolView,BoolView,RM_IMP>::
00237                           post(home,x,c,r.var())));
00238           break;
00239         case RM_PMI:
00240           GECODE_ES_FAIL((ReGqBoolInt<BoolView,BoolView,RM_PMI>::
00241                           post(home,x,c,r.var())));
00242           break;
00243         default: GECODE_NEVER;
00244         }
00245       }
00246       break;
00247     case IRT_LQ:
00248       {
00249         ViewArray<NegBoolView> x(home,n_p);
00250         for (int i=n_p; i--; )
00251           x[i]=NegBoolView(t_p[i].x);
00252         switch (r.mode()) {
00253         case RM_EQV:
00254           GECODE_ES_FAIL((ReGqBoolInt<NegBoolView,BoolView,RM_EQV>::
00255                           post(home,x,n_p-c,r.var())));
00256           break;
00257         case RM_IMP:
00258           GECODE_ES_FAIL((ReGqBoolInt<NegBoolView,BoolView,RM_IMP>::
00259                           post(home,x,n_p-c,r.var())));
00260           break;
00261         case RM_PMI:
00262           GECODE_ES_FAIL((ReGqBoolInt<NegBoolView,BoolView,RM_PMI>::
00263                           post(home,x,n_p-c,r.var())));
00264           break;
00265         default: GECODE_NEVER;
00266         }
00267       }
00268       break;
00269     default: GECODE_NEVER;
00270     }
00271   }
00272 
00273   forceinline void
00274   post_neg_unit(Home home,
00275                 Term<BoolView>* t_n, int n_n,
00276                 IntRelType irt, IntView y, int c) {
00277     switch (irt) {
00278     case IRT_EQ:
00279       {
00280         ViewArray<BoolView> x(home,n_n);
00281         for (int i=n_n; i--; )
00282           x[i]=t_n[i].x;
00283         MinusView z(y);
00284         GECODE_ES_FAIL((EqBoolView<BoolView,MinusView>
00285                         ::post(home,x,z,-c)));
00286       }
00287       break;
00288     case IRT_NQ:
00289       {
00290         ViewArray<BoolView> x(home,n_n);
00291         for (int i=n_n; i--; )
00292           x[i]=t_n[i].x;
00293         MinusView z(y);
00294         GECODE_ES_FAIL((NqBoolView<BoolView,MinusView>
00295                         ::post(home,x,z,-c)));
00296       }
00297       break;
00298     case IRT_GQ:
00299       {
00300         ViewArray<NegBoolView> x(home,n_n);
00301         for (int i=n_n; i--; )
00302           x[i]=NegBoolView(t_n[i].x);
00303         GECODE_ES_FAIL((GqBoolView<NegBoolView,IntView>
00304                         ::post(home,x,y,n_n+c)));
00305       }
00306       break;
00307     case IRT_LQ:
00308       {
00309         ViewArray<BoolView> x(home,n_n);
00310         for (int i=n_n; i--; )
00311           x[i]=t_n[i].x;
00312         MinusView z(y);
00313         GECODE_ES_FAIL((GqBoolView<BoolView,MinusView>
00314                         ::post(home,x,z,-c)));
00315       }
00316       break;
00317     default: GECODE_NEVER;
00318     }
00319   }
00320 
00321   forceinline void
00322   post_neg_unit(Home home,
00323                 Term<BoolView>* t_n, int n_n,
00324                 IntRelType irt, ZeroIntView, int c) {
00325     switch (irt) {
00326     case IRT_EQ:
00327       {
00328         ViewArray<BoolView> x(home,n_n);
00329         for (int i=n_n; i--; )
00330           x[i]=t_n[i].x;
00331         GECODE_ES_FAIL((EqBoolInt<BoolView>::post(home,x,-c)));
00332       }
00333       break;
00334     case IRT_NQ:
00335       {
00336         ViewArray<BoolView> x(home,n_n);
00337         for (int i=n_n; i--; )
00338           x[i]=t_n[i].x;
00339         GECODE_ES_FAIL((NqBoolInt<BoolView>::post(home,x,-c)));
00340       }
00341       break;
00342     case IRT_GQ:
00343       {
00344         ViewArray<NegBoolView> x(home,n_n);
00345         for (int i=n_n; i--; )
00346           x[i]=NegBoolView(t_n[i].x);
00347         GECODE_ES_FAIL((GqBoolInt<NegBoolView>::post(home,x,n_n+c)));
00348       }
00349       break;
00350     case IRT_LQ:
00351       {
00352         ViewArray<BoolView> x(home,n_n);
00353         for (int i=n_n; i--; )
00354           x[i]=t_n[i].x;
00355         GECODE_ES_FAIL((GqBoolInt<BoolView>::post(home,x,-c)));
00356       }
00357       break;
00358     default: GECODE_NEVER;
00359     }
00360   }
00361 
00362   forceinline void
00363   post_neg_unit(Home home,
00364                 Term<BoolView>* t_n, int n_n,
00365                 IntRelType irt, int c, Reify r,
00366                 IntConLevel) {
00367     switch (irt) {
00368     case IRT_EQ:
00369       {
00370         ViewArray<BoolView> x(home,n_n);
00371         for (int i=n_n; i--; )
00372           x[i]=t_n[i].x;
00373         switch (r.mode()) {
00374         case RM_EQV:
00375           GECODE_ES_FAIL((ReEqBoolInt<BoolView,BoolView,RM_EQV>::
00376                           post(home,x,-c,r.var())));
00377           break;
00378         case RM_IMP:
00379           GECODE_ES_FAIL((ReEqBoolInt<BoolView,BoolView,RM_IMP>::
00380                           post(home,x,-c,r.var())));
00381           break;
00382         case RM_PMI:
00383           GECODE_ES_FAIL((ReEqBoolInt<BoolView,BoolView,RM_PMI>::
00384                           post(home,x,-c,r.var())));
00385           break;
00386         default: GECODE_NEVER;
00387         }
00388       }
00389       break;
00390     case IRT_NQ:
00391       {
00392         ViewArray<BoolView> x(home,n_n);
00393         for (int i=n_n; i--; )
00394           x[i]=t_n[i].x;
00395         NegBoolView nb(r.var());
00396         switch (r.mode()) {
00397         case RM_EQV:
00398           GECODE_ES_FAIL((ReEqBoolInt<BoolView,NegBoolView,RM_EQV>::
00399                           post(home,x,-c,nb)));
00400           break;
00401         case RM_IMP:
00402           GECODE_ES_FAIL((ReEqBoolInt<BoolView,NegBoolView,RM_PMI>::
00403                           post(home,x,-c,nb)));
00404           break;
00405         case RM_PMI:
00406           GECODE_ES_FAIL((ReEqBoolInt<BoolView,NegBoolView,RM_IMP>::
00407                           post(home,x,-c,nb)));
00408           break;
00409         default: GECODE_NEVER;
00410         }
00411       }
00412       break;
00413     case IRT_GQ:
00414       {
00415         ViewArray<NegBoolView> x(home,n_n);
00416         for (int i=n_n; i--; )
00417           x[i]=NegBoolView(t_n[i].x);
00418         switch (r.mode()) {
00419         case RM_EQV:
00420           GECODE_ES_FAIL((ReGqBoolInt<NegBoolView,BoolView,RM_EQV>::
00421                           post(home,x,n_n+c,r.var())));
00422           break;
00423         case RM_IMP:
00424           GECODE_ES_FAIL((ReGqBoolInt<NegBoolView,BoolView,RM_IMP>::
00425                           post(home,x,n_n+c,r.var())));
00426           break;
00427         case RM_PMI:
00428           GECODE_ES_FAIL((ReGqBoolInt<NegBoolView,BoolView,RM_PMI>::
00429                           post(home,x,n_n+c,r.var())));
00430           break;
00431         default: GECODE_NEVER;
00432         }
00433       }
00434       break;
00435     case IRT_LQ:
00436       {
00437         ViewArray<BoolView> x(home,n_n);
00438         for (int i=n_n; i--; )
00439           x[i]=t_n[i].x;
00440         switch (r.mode()) {
00441         case RM_EQV:
00442           GECODE_ES_FAIL((ReGqBoolInt<BoolView,BoolView,RM_EQV>::
00443                           post(home,x,-c,r.var())));
00444           break;
00445         case RM_IMP:
00446           GECODE_ES_FAIL((ReGqBoolInt<BoolView,BoolView,RM_IMP>::
00447                           post(home,x,-c,r.var())));
00448           break;
00449         case RM_PMI:
00450           GECODE_ES_FAIL((ReGqBoolInt<BoolView,BoolView,RM_PMI>::
00451                           post(home,x,-c,r.var())));
00452           break;
00453         default: GECODE_NEVER;
00454         }
00455       }
00456       break;
00457     default: GECODE_NEVER;
00458     }
00459   }
00460 
00461   forceinline void
00462   post_mixed(Home home,
00463              Term<BoolView>* t_p, int n_p,
00464              Term<BoolView>* t_n, int n_n,
00465              IntRelType irt, IntView y, int c) {
00466     ScaleBoolArray b_p(home,n_p);
00467     {
00468       ScaleBool* f=b_p.fst();
00469       for (int i=n_p; i--; ) {
00470         f[i].x=t_p[i].x; f[i].a=t_p[i].a;
00471       }
00472     }
00473     ScaleBoolArray b_n(home,n_n);
00474     {
00475       ScaleBool* f=b_n.fst();
00476       for (int i=n_n; i--; ) {
00477         f[i].x=t_n[i].x; f[i].a=t_n[i].a;
00478       }
00479     }
00480     switch (irt) {
00481     case IRT_EQ:
00482       GECODE_ES_FAIL((EqBoolScale<ScaleBoolArray,ScaleBoolArray,IntView>
00483                       ::post(home,b_p,b_n,y,c)));
00484       break;
00485     case IRT_NQ:
00486       GECODE_ES_FAIL((NqBoolScale<ScaleBoolArray,ScaleBoolArray,IntView>
00487                       ::post(home,b_p,b_n,y,c)));
00488       break;
00489     case IRT_LQ:
00490       GECODE_ES_FAIL((LqBoolScale<ScaleBoolArray,ScaleBoolArray,IntView>
00491                       ::post(home,b_p,b_n,y,c)));
00492       break;
00493     case IRT_GQ:
00494       {
00495         MinusView m(y);
00496         GECODE_ES_FAIL((LqBoolScale<ScaleBoolArray,ScaleBoolArray,MinusView>
00497                         ::post(home,b_n,b_p,m,-c)));
00498       }
00499       break;
00500     default:
00501       GECODE_NEVER;
00502     }
00503   }
00504 
00505 
00506   forceinline void
00507   post_mixed(Home home,
00508              Term<BoolView>* t_p, int n_p,
00509              Term<BoolView>* t_n, int n_n,
00510              IntRelType irt, ZeroIntView y, int c) {
00511     ScaleBoolArray b_p(home,n_p);
00512     {
00513       ScaleBool* f=b_p.fst();
00514       for (int i=n_p; i--; ) {
00515         f[i].x=t_p[i].x; f[i].a=t_p[i].a;
00516       }
00517     }
00518     ScaleBoolArray b_n(home,n_n);
00519     {
00520       ScaleBool* f=b_n.fst();
00521       for (int i=n_n; i--; ) {
00522         f[i].x=t_n[i].x; f[i].a=t_n[i].a;
00523       }
00524     }
00525     switch (irt) {
00526     case IRT_EQ:
00527       GECODE_ES_FAIL(
00528                      (EqBoolScale<ScaleBoolArray,ScaleBoolArray,ZeroIntView>
00529                       ::post(home,b_p,b_n,y,c)));
00530       break;
00531     case IRT_NQ:
00532       GECODE_ES_FAIL(
00533                      (NqBoolScale<ScaleBoolArray,ScaleBoolArray,ZeroIntView>
00534                       ::post(home,b_p,b_n,y,c)));
00535       break;
00536     case IRT_LQ:
00537       GECODE_ES_FAIL(
00538                      (LqBoolScale<ScaleBoolArray,ScaleBoolArray,ZeroIntView>
00539                       ::post(home,b_p,b_n,y,c)));
00540       break;
00541     case IRT_GQ:
00542       GECODE_ES_FAIL(
00543                      (LqBoolScale<ScaleBoolArray,ScaleBoolArray,ZeroIntView>
00544                       ::post(home,b_n,b_p,y,-c)));
00545       break;
00546     default:
00547       GECODE_NEVER;
00548     }
00549   }
00550 
00551   template<class View>
00552   forceinline void
00553   post_all(Home home,
00554            Term<BoolView>* t, int n,
00555            IntRelType irt, View x, int c) {
00556 
00557     Limits::check(c,"Int::linear");
00558 
00559     long long int d = c;
00560 
00561     eliminate(t,n,d);
00562 
00563     Term<BoolView> *t_p, *t_n;
00564     int n_p, n_n, gcd=0;
00565     bool unit = normalize<BoolView>(t,n,t_p,n_p,t_n,n_n,gcd);
00566 
00567     rewrite(irt,d);
00568 
00569     c = static_cast<int>(d);
00570 
00571     if (n == 0) {
00572       switch (irt) {
00573       case IRT_EQ: GECODE_ME_FAIL(x.eq(home,-c)); break;
00574       case IRT_NQ: GECODE_ME_FAIL(x.nq(home,-c)); break;
00575       case IRT_GQ: GECODE_ME_FAIL(x.lq(home,-c)); break;
00576       case IRT_LQ: GECODE_ME_FAIL(x.gq(home,-c)); break;
00577       default: GECODE_NEVER;
00578       }
00579       return;
00580     }
00581 
00582     // Check for overflow
00583     {
00584       long long int sl = static_cast<long long int>(x.max())+c;
00585       long long int su = static_cast<long long int>(x.min())+c;
00586       for (int i=n_p; i--; )
00587         su -= t_p[i].a;
00588       for (int i=n_n; i--; )
00589         sl += t_n[i].a;
00590       Limits::check(sl,"Int::linear");
00591       Limits::check(su,"Int::linear");
00592     }
00593 
00594     if (unit && (n_n == 0)) {
00596       post_pos_unit(home,t_p,n_p,irt,x,c);
00597     } else if (unit && (n_p == 0)) {
00598       // All coefficients are -1
00599       post_neg_unit(home,t_n,n_n,irt,x,c);
00600     } else {
00601       // Mixed coefficients
00602       post_mixed(home,t_p,n_p,t_n,n_n,irt,x,c);
00603     }
00604   }
00605 
00606 
00607   void
00608   post(Home home,
00609        Term<BoolView>* t, int n, IntRelType irt, IntView x, int c,
00610        IntConLevel) {
00611     post_all(home,t,n,irt,x,c);
00612   }
00613 
00614   void
00615   post(Home home,
00616        Term<BoolView>* t, int n, IntRelType irt, int c,
00617        IntConLevel) {
00618     ZeroIntView x;
00619     post_all(home,t,n,irt,x,c);
00620   }
00621 
00622   void
00623   post(Home home,
00624        Term<BoolView>* t, int n, IntRelType irt, IntView x, Reify r,
00625        IntConLevel icl) {
00626     int l, u;
00627     estimate(t,n,0,l,u);
00628     IntVar z(home,l,u); IntView zv(z);
00629     post_all(home,t,n,IRT_EQ,zv,0);
00630     rel(home,z,irt,x,r,icl);
00631   }
00632 
00633   void
00634   post(Home home,
00635        Term<BoolView>* t, int n, IntRelType irt, int c, Reify r,
00636        IntConLevel icl) {
00637 
00638     if (r.var().one()) {
00639       if (r.mode() != RM_PMI)
00640         post(home,t,n,irt,c,icl);
00641       return;
00642     }
00643     if (r.var().zero()) {
00644       if (r.mode() != RM_IMP)
00645         post(home,t,n,inverse(irt),c,icl);
00646       return;
00647     }
00648 
00649     Limits::check(c,"Int::linear");
00650 
00651     long long int d = c;
00652 
00653     eliminate(t,n,d);
00654 
00655     Term<BoolView> *t_p, *t_n;
00656     int n_p, n_n, gcd=1;
00657     bool unit = normalize<BoolView>(t,n,t_p,n_p,t_n,n_n,gcd);
00658 
00659     rewrite(irt,d);
00660 
00661     // Divide by gcd
00662     if (gcd > 1) {
00663       switch (irt) {
00664       case IRT_EQ:
00665         if ((d % gcd) != 0) {
00666           if (r.mode() != RM_PMI)
00667             GECODE_ME_FAIL(BoolView(r.var()).zero(home));
00668           return;
00669         }
00670         d /= gcd;
00671         break;
00672       case IRT_NQ: 
00673         if ((d % gcd) == 0) {
00674           if (r.mode() != RM_IMP)
00675             GECODE_ME_FAIL(BoolView(r.var()).one(home));
00676           return;
00677         }
00678         d /= gcd;
00679         break;
00680       case IRT_LQ:
00681         d = floor_div_xp(d,static_cast<long long int>(gcd));
00682         break;
00683       case IRT_GQ:
00684         d = ceil_div_xp(d,static_cast<long long int>(gcd));
00685         break;
00686       default: GECODE_NEVER;
00687       }
00688     }
00689 
00690     c = static_cast<int>(d);
00691 
00692     if (n == 0) {
00693       bool fail = false;
00694       switch (irt) {
00695       case IRT_EQ: fail = (0 != c); break;
00696       case IRT_NQ: fail = (0 == c); break;
00697       case IRT_GQ: fail = (0 < c); break;
00698       case IRT_LQ: fail = (0 > c); break;
00699       default: GECODE_NEVER;
00700       }
00701       if (fail) {
00702         if (r.mode() != RM_PMI)
00703           GECODE_ME_FAIL(BoolView(r.var()).zero(home));
00704       } else {
00705         if (r.mode() != RM_IMP)
00706           GECODE_ME_FAIL(BoolView(r.var()).one(home));
00707       }
00708       return;
00709     }
00710 
00711     // Check for overflow
00712     {
00713       long long int sl = c;
00714       long long int su = c;
00715       for (int i=n_p; i--; )
00716         su -= t_p[i].a;
00717       for (int i=n_n; i--; )
00718         sl += t_n[i].a;
00719       Limits::check(sl,"Int::linear");
00720       Limits::check(su,"Int::linear");
00721     }
00722 
00723     if (unit && (n_n == 0)) {
00725       post_pos_unit(home,t_p,n_p,irt,c,r,icl);
00726     } else if (unit && (n_p == 0)) {
00727       // All coefficients are -1
00728       post_neg_unit(home,t_n,n_n,irt,c,r,icl);
00729     } else {
00730       // Mixed coefficients
00731       /*
00732        * Denormalize: Make all t_n coefficients negative again
00733        * (t_p and t_n are shared in t)
00734        */
00735       for (int i=n_n; i--; )
00736         t_n[i].a = -t_n[i].a;
00737 
00738       // Note: still slow implementation
00739       int l, u;
00740       estimate(t,n,0,l,u);
00741       IntVar z(home,l,u); IntView zv(z);
00742       post_all(home,t,n,IRT_EQ,zv,0);
00743       rel(home,z,irt,c,r,icl);
00744     }
00745   }
00746 
00747 }}}
00748 
00749 // STATISTICS: int-post
00750