link-multi.cc
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
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
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
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
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
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
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
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
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
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
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
00231