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

nary.hpp

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  *     Vincent Barichard <Vincent.Barichard@univ-angers.fr>
00006  *
00007  *  Copyright:
00008  *     Christian Schulte, 2003
00009  *     Vincent Barichard, 2012
00010  *
00011  *  Last modified:
00012  *     $Date: 2013-02-13 16:01:33 +0100 (Wed, 13 Feb 2013) $ by $Author: vbarichard $
00013  *     $Revision: 13289 $
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 namespace Gecode { namespace Float { namespace Linear {
00041 
00042   /*
00043    * Linear propagators
00044    *
00045    */
00046   template<class P, class N, PropCond pc>
00047   forceinline
00048   Lin<P,N,pc>::Lin(Home home, ViewArray<P>& x0, ViewArray<N>& y0, FloatVal c0)
00049     : Propagator(home), x(x0), y(y0), c(c0) {
00050     x.subscribe(home,*this,pc);
00051     y.subscribe(home,*this,pc);
00052   }
00053 
00054   template<class P, class N, PropCond pc>
00055   forceinline
00056   Lin<P,N,pc>::Lin(Space& home, bool share, Lin<P,N,pc>& p)
00057     : Propagator(home,share,p), c(p.c) {
00058     x.update(home,share,p.x);
00059     y.update(home,share,p.y);
00060   }
00061 
00062   template<class P, class N, PropCond pc>
00063   PropCost
00064   Lin<P,N,pc>::cost(const Space&, const ModEventDelta&) const {
00065     return PropCost::linear(PropCost::LO, x.size()+y.size());
00066   }
00067 
00068   template<class P, class N, PropCond pc>
00069   forceinline size_t
00070   Lin<P,N,pc>::dispose(Space& home) {
00071     x.cancel(home,*this,pc);
00072     y.cancel(home,*this,pc);
00073     (void) Propagator::dispose(home);
00074     return sizeof(*this);
00075   }
00076 
00077 
00078   /*
00079    * Computing bounds
00080    *
00081    */
00082 //  template<class View>
00083 //  void
00084 //  bounds_p(Rounding& r, ModEventDelta med, ViewArray<View>& x, FloatVal& c, FloatNum& sl, FloatNum& su) {
00085 //    int n = x.size();
00086 //    if (FloatView::me(med) == ME_FLOAT_VAL) {
00087 //      for (int i = n; i--; ) {
00088 //        if (x[i].assigned()) {
00089 //          c -= x[i].val(); x[i] = x[--n];
00090 //        } else {
00091 //          sl = r.sub_up(sl,x[i].min()); su = r.sub_down(su,x[i].max());
00092 //        }
00093 //      }
00094 //      x.size(n);
00095 //    } else {
00096 //      for (int i = n; i--; ) {
00097 //        sl = r.sub_up(sl,x[i].min()); su = r.sub_down(su,x[i].max());
00098 //      }
00099 //    }
00100 //  }
00101 //
00102 //  template<class View>
00103 //  void
00104 //  bounds_n(Rounding& r, ModEventDelta med, ViewArray<View>& y, FloatVal& c, FloatNum& sl, FloatNum& su) {
00105 //    int n = y.size();
00106 //    if (FloatView::me(med) == ME_FLOAT_VAL) {
00107 //      for (int i = n; i--; ) {
00108 //        if (y[i].assigned()) {
00109 //          c += y[i].val(); y[i] = y[--n];
00110 //        } else {
00111 //          sl = r.add_up(sl,y[i].max()); su = r.add_down(su,y[i].min());
00112 //        }
00113 //      }
00114 //      y.size(n);
00115 //    } else {
00116 //      for (int i = n; i--; ) {
00117 //        sl = r.add_up(sl,y[i].max()); su = r.add_down(su,y[i].min());
00118 //      }
00119 //    }
00120 //  }
00121 
00122   template<class View>
00123   void
00124   eliminate_p(ModEventDelta med, ViewArray<View>& x, FloatVal& c) {
00125     int n = x.size();
00126 
00127     if (FloatView::me(med) == ME_FLOAT_VAL) {
00128       for (int i = n; i--; ) {
00129         if (x[i].assigned()) {
00130           c -= x[i].val(); x[i] = x[--n];
00131         }
00132       }
00133       x.size(n);
00134     }
00135   }
00136 
00137   template<class View>
00138   void
00139   eliminate_n(ModEventDelta med, ViewArray<View>& y, FloatVal& c) {
00140     int n = y.size();
00141     if (FloatView::me(med) == ME_FLOAT_VAL) {
00142       for (int i = n; i--; ) {
00143         if (y[i].assigned()) {
00144           c += y[i].val(); y[i] = y[--n];
00145         }
00146       }
00147       y.size(n);
00148     }
00149   }
00150 
00151   forceinline bool 
00152   infty(const FloatNum& n) {
00153     return ((n == std::numeric_limits<FloatNum>::infinity()) || 
00154             (n == -std::numeric_limits<FloatNum>::infinity()));
00155   }
00156 
00157   /*
00158    * Bound consistent linear equation
00159    *
00160    */
00161 
00162   template<class P, class N>
00163   forceinline
00164   Eq<P,N>::Eq(Home home, ViewArray<P>& x, ViewArray<N>& y, FloatVal c)
00165     : Lin<P,N,PC_FLOAT_BND>(home,x,y,c) {}
00166 
00167   template<class P, class N>
00168   ExecStatus
00169   Eq<P,N>::post(Home home, ViewArray<P>& x, ViewArray<N>& y, FloatVal c) {
00170     (void) new (home) Eq<P,N>(home,x,y,c);
00171     return ES_OK;
00172   }
00173 
00174 
00175   template<class P, class N>
00176   forceinline
00177   Eq<P,N>::Eq(Space& home, bool share, Eq<P,N>& p)
00178     : Lin<P,N,PC_FLOAT_BND>(home,share,p) {}
00179 
00180   template<class P, class N>
00181   Actor*
00182   Eq<P,N>::copy(Space& home, bool share) {
00183     return new (home) Eq<P,N>(home,share,*this);
00184   }
00185 
00186   template<class P, class N>
00187   ExecStatus
00188   Eq<P,N>::propagate(Space& home, const ModEventDelta& med) {
00189     // Eliminate singletons
00190     Rounding r;
00191     eliminate_p<P>(med, x, c);
00192     eliminate_n<N>(med, y, c);
00193 
00194     if ((FloatView::me(med) == ME_FLOAT_VAL) && ((x.size() + y.size()) <= 1)) {
00195       if (x.size() == 1) {
00196         GECODE_ME_CHECK(x[0].eq(home,c));
00197         return home.ES_SUBSUMED(*this);
00198       }
00199       if (y.size() == 1) {
00200         GECODE_ME_CHECK(y[0].eq(home,-c));
00201         return home.ES_SUBSUMED(*this);
00202       }
00203       return (c.in(0.0)) ? home.ES_SUBSUMED(*this) : ES_FAILED;
00204     }
00205 
00206     ExecStatus es = ES_FIX;
00207     bool assigned = true;
00208 
00209     // Propagate max bound for positive variables
00210     for (int i = x.size(); i--; ) {
00211       // Compute bound
00212       FloatNum sl = c.max();
00213       for (int j = x.size(); j--; ) {
00214         if (i == j) continue;
00215         sl = r.sub_up(sl,x[j].min());
00216       }
00217       for (int j = y.size(); j--; )
00218         sl = r.add_up(sl,y[j].max());
00219       ModEvent me = x[i].lq(home,sl);
00220       if (me_failed(me))
00221         return ES_FAILED;
00222       if (me != ME_FLOAT_VAL)
00223         assigned = false;
00224       if (me_modified(me))
00225         es = ES_NOFIX;
00226     }
00227     // Propagate min bound for negative variables
00228     for (int i = y.size(); i--; ) {
00229       // Compute bound
00230       FloatNum sl = -c.max();
00231       for (int j = x.size(); j--; )
00232         sl = r.add_down(sl,x[j].min());
00233       for (int j = y.size(); j--; ) {
00234         if (i == j) continue;
00235         sl = r.sub_down(sl,y[j].max());
00236       }
00237       ModEvent me = y[i].gq(home,sl);
00238       if (me_failed(me))
00239         return ES_FAILED;
00240       if (me != ME_FLOAT_VAL)
00241         assigned = false;
00242       if (me_modified(me))
00243         es = ES_NOFIX;
00244     }
00245    
00246     // Propagate min bound for positive variables
00247     for (int i = x.size(); i--; ) {
00248       // Compute bound
00249       FloatNum su = c.min();
00250       for (int j = x.size(); j--; ) {
00251         if (i == j) continue;
00252         su = r.sub_down(su,x[j].max());
00253       }
00254       for (int j = y.size(); j--; )
00255         su = r.add_down(su,y[j].min());
00256       ModEvent me = x[i].gq(home,su);
00257       if (me_failed(me))
00258         return ES_FAILED;
00259       if (me != ME_FLOAT_VAL)
00260         assigned = false;
00261       if (me_modified(me))
00262         es = ES_NOFIX;
00263     }
00264     // Propagate max bound for negative variables
00265     for (int i = y.size(); i--; ) {
00266       // Compute bound
00267       FloatNum su = -c.min();
00268       for (int j = x.size(); j--; )
00269         su = r.add_up(su,x[j].max());
00270       for (int j = y.size(); j--; ) {
00271         if (i == j) continue;
00272         su = r.sub_up(su,y[j].min());
00273       }
00274       ModEvent me = y[i].lq(home,su);
00275       if (me_failed(me))
00276         return ES_FAILED;
00277       if (me != ME_FLOAT_VAL)
00278         assigned = false;
00279       if (me_modified(me))
00280         es = ES_NOFIX;
00281     }
00282 
00283     return assigned ? home.ES_SUBSUMED(*this) : es;
00284   }
00285 
00286 
00287   /*
00288    * Bound consistent linear inequation
00289    *
00290    */
00291 
00292   template<class P, class N>
00293   forceinline
00294   Lq<P,N>::Lq(Home home, ViewArray<P>& x, ViewArray<N>& y, FloatVal c)
00295     : Lin<P,N,PC_FLOAT_BND>(home,x,y,c) {}
00296 
00297   template<class P, class N>
00298   ExecStatus
00299   Lq<P,N>::post(Home home, ViewArray<P>& x, ViewArray<N>& y, FloatVal c) {
00300     (void) new (home) Lq<P,N>(home,x,y,c);
00301     return ES_OK;
00302   }
00303 
00304   template<class P, class N>
00305   forceinline
00306   Lq<P,N>::Lq(Space& home, bool share, Lq<P,N>& p)
00307     : Lin<P,N,PC_FLOAT_BND>(home,share,p) {}
00308 
00309   template<class P, class N>
00310   Actor*
00311   Lq<P,N>::copy(Space& home, bool share) {
00312     return new (home) Lq<P,N>(home,share,*this);
00313   }
00314 
00315   template<class P, class N>
00316   ExecStatus
00317   Lq<P,N>::propagate(Space& home, const ModEventDelta& med) {
00318     // Eliminate singletons
00319     FloatNum sl = 0.0;
00320 
00321     Rounding r;
00322 
00323     if (FloatView::me(med) == ME_FLOAT_VAL) {
00324       for (int i = x.size(); i--; ) {
00325         if (x[i].assigned()) {
00326           c  -= x[i].val();  x.move_lst(i);
00327         } else {
00328           sl = r.sub_up(sl,x[i].min());
00329         }
00330       }
00331       for (int i = y.size(); i--; ) {
00332         if (y[i].assigned()) {
00333           c  += y[i].val();  y.move_lst(i);
00334         } else {
00335           sl = r.add_up(sl,y[i].max());
00336         }
00337       }
00338       if ((x.size() + y.size()) <= 1) {
00339         if (x.size() == 1) {
00340           GECODE_ME_CHECK(x[0].lq(home,c.max()));
00341           return home.ES_SUBSUMED(*this);
00342         }
00343         if (y.size() == 1) {
00344           GECODE_ME_CHECK(y[0].gq(home,(-c).min()));
00345           return home.ES_SUBSUMED(*this);
00346         }
00347         return (c.max() >= 0) ? home.ES_SUBSUMED(*this) : ES_FAILED;
00348       }
00349     } else {
00350       for (int i = x.size(); i--; )
00351         sl = r.sub_up(sl,x[i].min());
00352       for (int i = y.size(); i--; )
00353         sl = r.add_up(sl,y[i].max());
00354     }
00355 
00356     sl = r.add_up(sl,c.max());
00357 
00358     ExecStatus es = ES_FIX;
00359     bool assigned = true;
00360     for (int i = x.size(); i--; ) {
00361       assert(!x[i].assigned());
00362       FloatNum slx = r.add_up(sl,x[i].min());
00363       ModEvent me = x[i].lq(home,slx);
00364       if (me == ME_FLOAT_FAILED)
00365         return ES_FAILED;
00366       if (me != ME_FLOAT_VAL)
00367         assigned = false;
00368       if (me_modified(me))
00369         es = ES_NOFIX;
00370     }
00371 
00372     for (int i = y.size(); i--; ) {
00373       assert(!y[i].assigned());
00374       FloatNum sly = r.sub_up(y[i].max(),sl);
00375       ModEvent me = y[i].gq(home,sly);
00376       if (me == ME_FLOAT_FAILED)
00377         return ES_FAILED;
00378       if (me != ME_FLOAT_VAL)
00379         assigned = false;
00380       if (me_modified(me))
00381         es = ES_NOFIX;
00382     }
00383 
00384     return assigned ? home.ES_SUBSUMED(*this) : es;
00385   }
00386 
00387 }}}
00388 
00389 // STATISTICS: float-prop
00390