Generated on Thu Mar 22 10:39:35 2012 for Gecode by doxygen 1.6.3

link-multi.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, 2007
00008  *
00009  *  Last modified:
00010  *     $Date: 2011-07-07 11:23:22 +0200 (Thu, 07 Jul 2011) $ by $Author: schulte $
00011  *     $Revision: 12155 $
00012  *
00013  *  This file is part of Gecode, the generic constraint
00014  *  development environment:
00015  *     http://www.gecode.org
00016  *
00017  *  Permission is hereby granted, free of charge, to any person obtaining
00018  *  a copy of this software and associated documentation files (the
00019  *  "Software"), to deal in the Software without restriction, including
00020  *  without limitation the rights to use, copy, modify, merge, publish,
00021  *  distribute, sublicense, and/or sell copies of the Software, and to
00022  *  permit persons to whom the Software is furnished to do so, subject to
00023  *  the following conditions:
00024  *
00025  *  The above copyright notice and this permission notice shall be
00026  *  included in all copies or substantial portions of the Software.
00027  *
00028  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00029  *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00030  *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00031  *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
00032  *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
00033  *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
00034  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00035  *
00036  */
00037 
00038 #include <gecode/int/channel.hh>
00039 
00040 namespace Gecode { namespace Int { namespace Channel {
00041 
00043   class BoolIter {
00044   private:
00046     const ViewArray<BoolView>& x;
00048     const int o;
00050     int i;
00051   public:
00053     BoolIter(const ViewArray<BoolView>& x0, int o0);
00055     bool operator ()(void) const;
00057     int val(void) const;
00059     void operator ++(void);
00060   };
00061 
00062   forceinline
00063   BoolIter::BoolIter(const ViewArray<BoolView>& x0, int o0) :
00064     x(x0), o(o0), i(0) {
00065     while ((i<x.size()) && !x[i].zero())
00066       i++;
00067   }
00068   forceinline bool
00069   BoolIter::operator ()(void) const {
00070     return i<x.size();
00071   }
00072   forceinline int
00073   BoolIter::val(void) const {
00074     assert(x[i].zero());
00075     return i+o;
00076   }
00077   forceinline void
00078   BoolIter::operator ++(void) {
00079     do {
00080       i++;
00081     } while ((i<x.size()) && !x[i].zero());
00082   }
00083 
00084 
00085   forceinline
00086   LinkMulti::LinkMulti(Space& home, bool share, LinkMulti& p)
00087     : MixNaryOnePropagator<BoolView,PC_BOOL_NONE,IntView,PC_INT_DOM>
00088   (home,share,p), status(S_NONE), o(p.o) {
00089     assert(p.status == S_NONE);
00090     c.update(home,share,p.c);
00091   }
00092 
00093   Actor*
00094   LinkMulti::copy(Space& home, bool share) {
00095     return new (home) LinkMulti(home,share,*this);
00096   }
00097 
00098   forceinline size_t
00099   LinkMulti::dispose(Space& home) {
00100     Advisors<Advisor> as(c);
00101     x.cancel(home,as.advisor());
00102     c.dispose(home);
00103     (void) MixNaryOnePropagator<BoolView,PC_BOOL_NONE,IntView,PC_INT_DOM>
00104       ::dispose(home);
00105     return sizeof(*this);
00106   }
00107 
00108   PropCost
00109   LinkMulti::cost(const Space&, const ModEventDelta& med) const {
00110     if ((status == S_ONE) || (IntView::me(med) == ME_INT_VAL))
00111       return PropCost::unary(PropCost::LO);
00112     else
00113       return PropCost::linear(PropCost::LO, x.size());
00114   }
00115 
00116   ExecStatus
00117   LinkMulti::advise(Space&, Advisor&, const Delta& d) {
00118     if (status == S_RUN)
00119       return ES_FIX;
00120     // Detect a one
00121     if (BoolView::one(d))
00122       status = S_ONE;
00123     return ES_NOFIX;
00124   }
00125 
00126   ExecStatus
00127   LinkMulti::propagate(Space& home, const ModEventDelta& med) {
00128     int n = x.size();
00129 
00130     // Always maintain the invariant that y lies inside the x-array
00131     assert((y.min()-o >= 0) && (y.max()-o < n));
00132 
00133     if (y.assigned()) {
00134       status = S_RUN;
00135       int j=y.val()-o;
00136       GECODE_ME_CHECK(x[j].one(home));
00137       for (int i=0; i<j; i++)
00138         GECODE_ME_CHECK(x[i].zero(home));
00139       for (int i=j+1; i<n; i++)
00140         GECODE_ME_CHECK(x[i].zero(home));
00141       return home.ES_SUBSUMED(*this);
00142     }
00143 
00144     // Check whether there is a one
00145     if (status == S_ONE) {
00146       status = S_RUN;
00147       for (int i=0; true; i++)
00148         if (x[i].one()) {
00149           for (int j=0; j<i; j++)
00150             GECODE_ME_CHECK(x[j].zero(home));
00151           for (int j=i+1; j<n; j++)
00152             GECODE_ME_CHECK(x[j].zero(home));
00153           GECODE_ME_CHECK(y.eq(home,i+o));
00154           return home.ES_SUBSUMED(*this);
00155         }
00156       GECODE_NEVER;
00157     }
00158 
00159     status = S_RUN;
00160 
00161   redo:
00162 
00163     // Assign all Boolean views to zero that are outside bounds
00164     {
00165       int min=y.min()-o;
00166       for (int i=0; i<min; i++)
00167         GECODE_ME_CHECK(x[i].zero(home));
00168       x.drop_fst(min); o += min; n = x.size();
00169 
00170       int max=y.max()-o;
00171       for (int i=max+1; i<n; i++)
00172         GECODE_ME_CHECK(x[i].zero(home));
00173       x.drop_lst(max); n = x.size();
00174     }
00175 
00176     {
00177       // Remove zeros on the left
00178       int i=0;
00179       while ((i < n) && x[i].zero()) i++;
00180       if (i >= n)
00181         return ES_FAILED;
00182       x.drop_fst(i); o += i; n = x.size();
00183     }
00184 
00185     {
00186       // Remove zeros on the right
00187       int i=n-1;
00188       while ((i >= 0) && x[i].zero()) i--;
00189       assert(i >= 0);
00190       x.drop_lst(i); n = x.size();
00191     }
00192 
00193     assert(n >= 1);
00194 
00195     // Is there only one left?
00196     if (n == 1) {
00197       GECODE_ME_CHECK(x[0].one(home));
00198       GECODE_ME_CHECK(y.eq(home,o));
00199       return home.ES_SUBSUMED(*this);
00200     }
00201 
00202     // Update bounds
00203     GECODE_ME_CHECK(y.gq(home,o));
00204     GECODE_ME_CHECK(y.lq(home,o+n-1));
00205     if ((y.min() > o) || (y.max() < o+n-1))
00206       goto redo;
00207 
00208     assert((n >= 2) && x[0].none() && x[n-1].none());
00209     assert((y.min()-o == 0) && (y.max()-o == n-1));
00210 
00211     // Propagate from y to Boolean views
00212     if ((IntView::me(med) == ME_INT_BND) || (IntView::me(med) == ME_INT_DOM)) {
00213       ViewValues<IntView> v(y);
00214       int i=0;
00215       do {
00216         int j = v.val()-o;
00217         if (i < j) {
00218           GECODE_ME_CHECK(x[i].zero(home));
00219           ++i;
00220         } else if (i > j) {
00221           ++v;
00222         } else {
00223           assert(i == j);
00224           ++i; ++v;
00225         }
00226       } while (v() && (i < n));
00227     }
00228 
00229     // Propagate from Boolean views to y
00230     if (BoolView::me(med) == ME_BOOL_VAL) {
00231       BoolIter bv(x,o);
00232       GECODE_ME_CHECK(y.minus_v(home,bv,false));
00233     }
00234     status = S_NONE;
00235     return ES_FIX;
00236   }
00237 
00238 }}}
00239 
00240 // STATISTICS: int-prop
00241