link-multi.cpp
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_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
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
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
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
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
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
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
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
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
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
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
00241