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

link-multi.cc

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: 2008-01-31 18:29:16 +0100 (Thu, 31 Jan 2008) $ by $Author: tack $
00011  *     $Revision: 6017 $
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_VAL,IntView,PC_INT_DOM>
00088   (home,share,p), o(p.o) {}
00089 
00090   Actor*
00091   LinkMulti::copy(Space* home, bool share) {
00092     return new (home) LinkMulti(home,share,*this);
00093   }
00094 
00095   PropCost
00096   LinkMulti::cost(ModEventDelta med) const {
00097     return (IntView::me(med) == ME_INT_VAL) ? 
00098       PC_UNARY_LO : cost_lo(x.size(),PC_LINEAR_LO);
00099   }
00100 
00101   Support::Symbol
00102   LinkMulti::ati(void) {
00103     return Support::Symbol("Gecode::Int::Channel::LinkMulti");
00104   }
00105   
00106   Reflection::ActorSpec
00107   LinkMulti::spec(const Space* home, Reflection::VarMap& m) const {
00108     Reflection::ActorSpec s =
00109       MixNaryOnePropagator<BoolView,PC_BOOL_VAL,IntView,PC_INT_DOM>
00110         ::spec(home, m, ati());
00111     return s << o;
00112   }
00113 
00114   void
00115   LinkMulti::post(Space* home, Reflection::VarMap& vars,
00116                   const Reflection::ActorSpec& spec) {
00117     spec.checkArity(3);
00118     ViewArray<BoolView> b(home, vars, spec[0]);
00119     IntView x(home, vars, spec[1]);
00120     int o = spec[2]->toInt();
00121     (void) new (home) LinkMulti(home, b, x, o);
00122   }
00123 
00124   ExecStatus
00125   LinkMulti::propagate(Space* home, ModEventDelta med) {
00126     int n = x.size();
00127 
00128     // Always maintain the invariant that y lies inside the x-array
00129     assert((y.min()-o >= 0) && (y.max()-o < n));
00130 
00131     if (y.assigned()) {
00132       int j=y.val()-o;
00133       GECODE_ME_CHECK(x[j].one(home));
00134       for (int i=0; i<j; i++)
00135         GECODE_ME_CHECK(x[i].zero(home));
00136       for (int i=j+1; i<n; i++)
00137         GECODE_ME_CHECK(x[i].zero(home));
00138       return ES_SUBSUMED(this,sizeof(*this));
00139     }
00140 
00141   redo:
00142 
00143     // Assign all Boolean views to zero that are outside bounds
00144     {
00145       int min=y.min()-o;
00146       for (int i=0; i<min; i++)
00147         GECODE_ME_CHECK(x[i].zero(home));
00148       x.drop_fst(min); o += min; n = x.size();
00149 
00150       int max=y.max()-o;
00151       for (int i=max+1; i<n; i++)
00152         GECODE_ME_CHECK(x[i].zero(home));
00153       x.drop_lst(max); n = x.size();
00154     }
00155 
00156     {
00157       // Remove zeros on the left
00158       int i=0;
00159       while ((i < n) && x[i].zero()) i++;
00160       if (i >= n)
00161         return ES_FAILED;
00162       x.drop_fst(i); o += i; n = x.size();
00163     }
00164 
00165     {
00166       // Remove zeros on the right
00167       int i=n-1;
00168       while ((i >= 0) && x[i].zero()) i--;
00169       assert(i >= 0);
00170       x.drop_lst(i); n = x.size();
00171     }
00172 
00173     assert(n >= 1);
00174 
00175     // Is there only one left?
00176     if (n == 1) {
00177       GECODE_ME_CHECK(x[0].one(home));
00178       GECODE_ME_CHECK(y.eq(home,o));
00179       return ES_SUBSUMED(this,sizeof(*this));
00180     }
00181 
00182     // Update bounds
00183     GECODE_ME_CHECK(y.gq(home,o));
00184     GECODE_ME_CHECK(y.lq(home,o+n-1));
00185     if ((y.min() > o) || (y.max() < o+n-1))
00186       goto redo;
00187 
00188     // Check whether there is a one somewhere else
00189     for (int i=n; i--; )
00190       if (x[i].one()) {
00191         for (int j=0; j<i; j++)
00192           GECODE_ME_CHECK(x[j].zero(home));
00193         for (int j=i+1; j<n; j++)
00194           GECODE_ME_CHECK(x[j].zero(home));
00195         GECODE_ME_CHECK(y.eq(home,i+o));
00196         return ES_SUBSUMED(this,sizeof(*this));
00197       }
00198 
00199     assert((n >= 2) && x[0].none() && x[n-1].none());
00200     assert((y.min()-o == 0) && (y.max()-o == n-1));
00201 
00202     // Propagate from y to Boolean views
00203     if ((IntView::me(med) == ME_INT_BND) || (IntView::me(med) == ME_INT_DOM)) {
00204       ViewValues<IntView> v(y);
00205       int i=0; 
00206       do {
00207         int j = v.val()-o;
00208         if (i < j) {
00209           GECODE_ME_CHECK(x[i].zero(home));
00210           ++i;
00211         } else if (i > j) {
00212           ++v;
00213         } else {
00214           assert(i == j);
00215           ++i; ++v;
00216         }
00217       } while (v() && (i < n));
00218     }
00219 
00220     // Propagate from Boolean views to y
00221     if (BoolView::me(med) == ME_BOOL_VAL) {
00222       BoolIter bv(x,o);
00223       GECODE_ME_CHECK(y.minus_v(home,bv,false));
00224     }
00225     return ES_FIX;
00226   }
00227 
00228 }}}
00229 
00230 // STATISTICS: int-prop
00231