Generated on Mon Aug 25 11:35:43 2008 for Gecode by doxygen 1.5.6

union.icc

Go to the documentation of this file.
00001 /* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
00002 /*
00003  *  Main authors:
00004  *     Guido Tack <tack@gecode.org>
00005  *     Christian Schulte <schulte@gecode.org>
00006  *
00007  *  Copyright:
00008  *     Guido Tack, 2004,2006
00009  *     Christian Schulte, 2004
00010  *
00011  *  Last modified:
00012  *     $Date: 2008-05-27 19:24:07 +0200 (Tue, 27 May 2008) $ by $Author: tack $
00013  *     $Revision: 6982 $
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 Set { namespace Element {
00041 
00042   template <class SView, class RView>
00043   forceinline
00044   ElementUnion<SView,RView>::
00045   ElementUnion(Space* home, SView y0,
00046                      IdxViewArray<SView>& iv0,
00047                      RView y1)
00048     : Propagator(home), x0(y0), iv(iv0), x1(y1) {
00049     force(home);
00050     x0.subscribe(home,this, PC_SET_ANY);
00051     x1.subscribe(home,this, PC_SET_ANY);
00052     iv.subscribe(home,this, PC_SET_ANY);
00053   }
00054 
00055   template <class SView, class RView>
00056   forceinline
00057   ElementUnion<SView,RView>::
00058   ElementUnion(Space* home, bool share,
00059                      ElementUnion<SView,RView>& p)
00060     : Propagator(home,share,p) {
00061     x0.update(home,share,p.x0);
00062     x1.update(home,share,p.x1);
00063     iv.update(home,share,p.iv);
00064   }
00065 
00066   template <class SView, class RView>
00067   PropCost
00068   ElementUnion<SView,RView>::cost(ModEventDelta) const {
00069     return PC_LINEAR_HI;
00070   }
00071 
00072   template <class SView, class RView>
00073   Support::Symbol
00074   ElementUnion<SView,RView>::ati(void) {
00075     return Reflection::mangle<SView,RView>("Gecode::Set::Element::Union");
00076   }
00077 
00078   template <class SView, class RView>
00079   Reflection::ActorSpec
00080   ElementUnion<SView,RView>::spec(const Space* home,
00081                                  Reflection::VarMap& m) const {
00082     Reflection::ActorSpec s(ati());
00083     return s << x0.spec(home, m)
00084              << iv.spec(home, m)
00085              << x1.spec(home, m);
00086   }
00087 
00088   template <class SView, class RView>
00089   void
00090   ElementUnion<SView,RView>::post(Space* home,
00091                                  Reflection::VarMap& vars,
00092                                  const Reflection::ActorSpec& spec) {
00093     spec.checkArity(3);
00094     SView x0(home, vars, spec[0]);
00095     IdxViewArray<SView> iv(home, vars, spec[1]);
00096     RView x1(home, vars, spec[2]);
00097     (void) new (home) ElementUnion(home, x0, iv, x1);
00098   }
00099 
00100   template <class SView, class RView>
00101   size_t
00102   ElementUnion<SView,RView>::dispose(Space* home) {
00103     unforce(home);
00104     if (!home->failed()) {
00105       x0.cancel(home,this, PC_SET_ANY);
00106       x1.cancel(home,this, PC_SET_ANY);
00107       iv.cancel(home,this,PC_SET_ANY);
00108     }
00109     (void) Propagator::dispose(home);
00110     return sizeof(*this);
00111   }
00112 
00113   template <class SView, class RView>
00114   ExecStatus
00115   ElementUnion<SView,RView>::
00116   post(Space* home, SView x0, IdxViewArray<SView>& xs,
00117        RView x1) {
00118     int n = xs.size();
00119 
00120     // s2 \subseteq {1,...,n}
00121     Iter::Ranges::Singleton s(0, n-1);
00122     GECODE_ME_CHECK(x1.intersectI(home,s));
00123     (void) new (home)
00124       ElementUnion<SView,RView>(home,x0,xs,x1);
00125     return ES_OK;
00126   }
00127 
00128   template <class SView, class RView>
00129   Actor*
00130   ElementUnion<SView,RView>::copy(Space* home, bool share) {
00131     return new (home) ElementUnion<SView,RView>(home,share,*this);
00132   }
00133 
00134   template <class SView, class RView>
00135   ExecStatus
00136   ElementUnion<SView,RView>::propagate(Space* home, ModEventDelta) {
00137     int n = iv.size();
00138 
00139     bool loopVar;
00140     do {
00141       loopVar = false;
00142 
00143       // Cache the upper bound iterator, as we have to
00144       // modify the upper bound while iterating
00145       LubRanges<RView> x1ub(x1);
00146       Iter::Ranges::Cache<LubRanges<RView> > x1ubc(x1ub);
00147       Iter::Ranges::ToValues<Iter::Ranges::Cache<LubRanges<RView> > >
00148         vx1ub(x1ubc);
00149 
00150       GlbRanges<RView> x1lb(x1);
00151       Iter::Ranges::Cache<GlbRanges<RView> > x1lbc(x1lb);
00152       Iter::Ranges::ToValues<Iter::Ranges::Cache<GlbRanges<RView> > >
00153         vx1(x1lbc);
00154 
00155       // In the first iteration, compute in before[i] the union
00156       // of all the upper bounds of the x_i. At the same time,
00157       // exclude inconsistent x_i from x1 and remove them from
00158       // the list, cancel their dependencies.
00159 
00160       GLBndSet sofarBefore(home);
00161       LUBndSet selectedInter(home, IntSet (Limits::min,
00162                                    Limits::max));
00163       GECODE_AUTOARRAY(GLBndSet, before, n);
00164 
00165       int j = 0;
00166       int i = 0;
00167       
00168       unsigned int maxCard = 0;
00169       unsigned int minCard = Limits::card;
00170       
00171       while ( vx1ub() ) {
00172 
00173         // Remove vars at indices not in the upper bound
00174         if (iv[i].idx < vx1ub.val()) {
00175           iv[i].var.cancel(home,this, PC_SET_ANY);
00176           ++i;
00177           continue;
00178         }
00179         assert(iv[i].idx == vx1ub.val());
00180         iv[j] = iv[i];
00181 
00182         SView candidate = iv[j].var;
00183         int candidateInd = iv[j].idx;
00184 
00185         // inter = glb(candidate) & complement(lub(x0))
00186         GlbRanges<SView> candlb(candidate);
00187         LubRanges<SView> x0ub(x0);
00188         Iter::Ranges::Diff<GlbRanges<SView>,
00189           LubRanges<SView> > diff(candlb, x0ub);
00190 
00191         bool selectSingleInconsistent = false;
00192         if (x1.cardMax() <= 1) {
00193           GlbRanges<SView> x0lb(x0);
00194           LubRanges<SView> candub(candidate);
00195           Iter::Ranges::Diff<GlbRanges<SView>,
00196                              LubRanges<SView> > diff2(x0lb, candub);
00197           selectSingleInconsistent = diff2() || candidate.cardMax() < x0.cardMin();
00198         }
00199 
00200         // exclude inconsistent x_i
00201         // an x_i is inconsistent if
00202         //  * at most one x_i can be selected and there are
00203         //    elements in x_0 that can't be in x_i
00204         //    (selectSingleInconsistent)
00205         //  * its min cardinality is greater than maxCard of x0
00206         //  * inter is not empty (there are elements in x_i
00207         //    that can't be in x_0)
00208         if (selectSingleInconsistent ||
00209             candidate.cardMin() > x0.cardMax() ||
00210             diff()) {
00211           ModEvent me = (x1.exclude(home,candidateInd));
00212           loopVar |= me_modified(me);
00213           GECODE_ME_CHECK(me);
00214 
00215           iv[j].var.cancel(home,this, PC_SET_ANY);
00216           ++i;
00217           ++vx1ub;
00218           continue;
00219         } else {
00220           // if x_i is consistent, check whether we know
00221           // that its index is in x1
00222           if (vx1() && vx1.val()==candidateInd) {
00223             // x0 >= candidate, candidate <= x0
00224             GlbRanges<SView> candlb(candidate);
00225             ModEvent me = x0.includeI(home,candlb);
00226             loopVar |= me_modified(me);
00227             GECODE_ME_CHECK(me);
00228 
00229             LubRanges<SView> x0ub(x0);
00230             me = candidate.intersectI(home,x0ub);
00231             loopVar |= me_modified(me);
00232             GECODE_ME_CHECK(me);
00233             ++vx1;
00234           }
00235           new (&before[j]) GLBndSet(home);
00236           before[j].update(home,sofarBefore);
00237           LubRanges<SView> cub(candidate);
00238           sofarBefore.includeI(home,cub);
00239           GlbRanges<SView> clb(candidate);
00240           selectedInter.intersectI(home,clb);
00241           maxCard = std::max(maxCard, candidate.cardMax());
00242           minCard = std::min(minCard, candidate.cardMin());
00243         }
00244 
00245         ++vx1ub;
00246         ++i; ++j;
00247       }
00248 
00249       // cancel the variables with index greater than
00250       // max of lub(x1)
00251       for (int k=i; k<n; k++) {
00252         iv[k].var.cancel(home,this, PC_SET_ANY);
00253       }
00254       n = j;
00255       iv.size(n);
00256 
00257       if (x1.cardMax()==0) {
00258         // Selector is empty, hence the result must be empty
00259         {
00260           GECODE_ME_CHECK(x0.cardMax(home,0));
00261         }
00262         for (int i=n; i--;)
00263           before[i].dispose(home);
00264         return ES_SUBSUMED(this,home);
00265       }
00266 
00267       if (x1.cardMin() > 0) {
00268         // Selector is not empty, hence the intersection of the
00269         // possibly selected lower bounds is contained in x0
00270         BndSetRanges si(selectedInter);
00271         ModEvent me = x0.includeI(home, si);
00272         loopVar |= me_modified(me);
00273         GECODE_ME_CHECK(me);
00274         me = x0.cardMin(home, minCard);
00275         loopVar |= me_modified(me);
00276         GECODE_ME_CHECK(me);
00277       }
00278       selectedInter.dispose(home);
00279 
00280       if (x1.cardMax() <= 1) {
00281         ModEvent me = x0.cardMax(home, maxCard);
00282         loopVar |= me_modified(me);
00283         GECODE_ME_CHECK(me);
00284       }
00285 
00286       {
00287         // x0 <= sofarBefore
00288         BndSetRanges sfB(sofarBefore);
00289         ModEvent me = x0.intersectI(home,sfB);
00290         loopVar |= me_modified(me);
00291         GECODE_ME_CHECK(me);
00292       }
00293 
00294       sofarBefore.dispose(home);
00295 
00296       GLBndSet sofarAfter(home);
00297 
00298       // In the second iteration, this time backwards, compute
00299       // sofarAfter as the union of all lub(x_j) with j>i
00300       for (int i=n; i--;) {
00301         // TODO: check for size of universe here?
00302         // if (sofarAfter.size() == 0) break;
00303         
00304         // extra = inter(before[i], sofarAfter) - lub(x0)
00305         BndSetRanges b(before[i]);
00306         BndSetRanges s(sofarAfter);
00307         GlbRanges<SView> x0lb(x0);
00308         Iter::Ranges::Union<BndSetRanges, BndSetRanges> inter(b,s);
00309         Iter::Ranges::Diff<GlbRanges<SView>,
00310           Iter::Ranges::Union<BndSetRanges,BndSetRanges> > diff(x0lb, inter);
00311         if (diff()) {
00312           ModEvent me = (x1.include(home,iv[i].idx));
00313           loopVar |= me_modified(me);
00314           GECODE_ME_CHECK(me);
00315 
00316           // candidate != extra
00317           me = iv[i].var.includeI(home,diff);
00318           loopVar |= me_modified(me);
00319           GECODE_ME_CHECK(me);
00320         }
00321 
00322         LubRanges<SView> iviub(iv[i].var);
00323         sofarAfter.includeI(home,iviub);
00324         before[i].dispose(home);
00325       }
00326       sofarAfter.dispose(home);
00327 
00328     } while (loopVar);
00329 
00330     // Test whether we determined x1 without determining x0
00331     if (x1.assigned() && !x0.assigned()) {
00332       int ubsize = x1.lubSize();
00333       if (ubsize > 2) {
00334         assert(ubsize==n);
00335         ViewArray<SView> is(home,ubsize);
00336         for (int i=n; i--;)
00337           is[i]=iv[i].var;
00338         GECODE_REWRITE(this,(RelOp::UnionN<SView, SView>
00339                         ::post(home,is,x0)));
00340       } else if (ubsize == 2) {
00341         assert(n==2);
00342         SView a = iv[0].var;
00343         SView b = iv[1].var;
00344         GECODE_REWRITE(this,(RelOp::Union<SView, SView, SView>
00345                        ::post(home,a,b,x0)));
00346       } else if (ubsize == 1) {
00347         assert(n==1);
00348         GECODE_REWRITE(this,(Rel::Eq<SView,SView>::post(home,x0,iv[0].var)));
00349       } else {
00350         GECODE_ME_CHECK(x0.cardMax(home, 0));
00351         return ES_SUBSUMED(this,home);
00352       }
00353     }
00354 
00355     bool allAssigned = true;
00356     for (int i=iv.size(); i--;) {
00357       if (!iv[i].var.assigned()) {
00358         allAssigned = false;
00359         break;
00360       }
00361     }
00362     if (x0.assigned() && x1.assigned() && allAssigned) {
00363       return ES_SUBSUMED(this,home);
00364     }
00365 
00366     return ES_FIX;
00367   }
00368 
00369 }}}
00370 
00371 // STATISTICS: set-prop