this repo has no description
1/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */ 2/* 3 * Main authors: 4 * Christian Schulte <schulte@gecode.org> 5 * 6 * Copyright: 7 * Christian Schulte, 2008 8 * 9 * This file is part of Gecode, the generic constraint 10 * development environment: 11 * http://www.gecode.org 12 * 13 * Permission is hereby granted, free of charge, to any person obtaining 14 * a copy of this software and associated documentation files (the 15 * "Software"), to deal in the Software without restriction, including 16 * without limitation the rights to use, copy, modify, merge, publish, 17 * distribute, sublicense, and/or sell copies of the Software, and to 18 * permit persons to whom the Software is furnished to do so, subject to 19 * the following conditions: 20 * 21 * The above copyright notice and this permission notice shall be 22 * included in all copies or substantial portions of the Software. 23 * 24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 28 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 29 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 30 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 31 * 32 */ 33 34namespace Gecode { namespace Int { namespace Bool { 35 36 /* 37 * Boolean clause propagator (disjunctive, true) 38 * 39 */ 40 41 template<class VX, class VY> 42 forceinline 43 ClauseTrue<VX,VY>::ClauseTrue(Home home, 44 ViewArray<VX>& x0, ViewArray<VY>& y0) 45 : MixBinaryPropagator<VX,PC_BOOL_VAL,VY,PC_BOOL_VAL> 46 (home,x0[x0.size()-1],y0[y0.size()-1]), x(x0), y(y0) { 47 assert((x.size() > 0) && (y.size() > 0)); 48 x.size(x.size()-1); y.size(y.size()-1); 49 } 50 51 template<class VX, class VY> 52 PropCost 53 ClauseTrue<VX,VY>::cost(const Space&, const ModEventDelta&) const { 54 return PropCost::binary(PropCost::LO); 55 } 56 57 template<class VX, class VY> 58 forceinline 59 ClauseTrue<VX,VY>::ClauseTrue(Space& home, ClauseTrue<VX,VY>& p) 60 : MixBinaryPropagator<VX,PC_BOOL_VAL,VY,PC_BOOL_VAL>(home,p) { 61 x.update(home,p.x); 62 y.update(home,p.y); 63 } 64 65 template<class VX, class VY> 66 Actor* 67 ClauseTrue<VX,VY>::copy(Space& home) { 68 { 69 int n = x.size(); 70 if (n > 0) { 71 // Eliminate all zeros and find a one 72 for (int i=n; i--; ) 73 if (x[i].one()) { 74 // Only keep the one 75 x[0]=x[i]; n=1; break; 76 } else if (x[i].zero()) { 77 // Eliminate the zero 78 x[i]=x[--n]; 79 } 80 x.size(n); 81 } 82 } 83 { 84 int n = y.size(); 85 if (n > 0) { 86 // Eliminate all zeros and find a one 87 for (int i=n; i--; ) 88 if (y[i].one()) { 89 // Only keep the one 90 y[0]=y[i]; n=1; break; 91 } else if (y[i].zero()) { 92 // Eliminate the zero 93 y[i]=y[--n]; 94 } 95 y.size(n); 96 } 97 } 98 if ((x.size() == 0) && (y.size() == 0)) 99 return new (home) BinOrTrue<VX,VY>(home,*this,x0,x1); 100 else 101 return new (home) ClauseTrue<VX,VY>(home,*this); 102 } 103 104 template<class VX, class VY> 105 inline ExecStatus 106 ClauseTrue<VX,VY>::post(Home home, ViewArray<VX>& x, ViewArray<VY>& y) { 107 for (int i=x.size(); i--; ) 108 if (x[i].one()) 109 return ES_OK; 110 else if (x[i].zero()) 111 x.move_lst(i); 112 if (x.size() == 0) 113 return NaryOrTrue<VY>::post(home,y); 114 for (int i=y.size(); i--; ) 115 if (y[i].one()) 116 return ES_OK; 117 else if (y[i].zero()) 118 y.move_lst(i); 119 if (y.size() == 0) 120 return NaryOrTrue<VX>::post(home,x); 121 if ((x.size() == 1) && (y.size() == 1)) { 122 return BinOrTrue<VX,VY>::post(home,x[0],y[0]); 123 } else if (!shared(x,y)) { 124 (void) new (home) ClauseTrue(home,x,y); 125 } 126 return ES_OK; 127 } 128 129 template<class VX, class VY> 130 forceinline size_t 131 ClauseTrue<VX,VY>::dispose(Space& home) { 132 (void) MixBinaryPropagator<VX,PC_BOOL_VAL,VY,PC_BOOL_VAL>::dispose(home); 133 return sizeof(*this); 134 } 135 136 template<class VX, class VY> 137 forceinline ExecStatus 138 resubscribe(Space& home, Propagator& p, 139 VX& x0, ViewArray<VX>& x, 140 VY& x1, ViewArray<VY>& y) { 141 if (x0.zero()) { 142 int n = x.size(); 143 for (int i=n; i--; ) 144 if (x[i].one()) { 145 x.size(n); 146 return home.ES_SUBSUMED(p); 147 } else if (x[i].zero()) { 148 x[i] = x[--n]; 149 } else { 150 // Rewrite if there is just one view left 151 if ((i == 0) && (y.size() == 0)) { 152 VX z = x[0]; x.size(0); 153 GECODE_REWRITE(p,(BinOrTrue<VX,VY>::post(home(p),z,x1))); 154 } 155 // Move to x0 and subscribe 156 x0=x[i]; x[i]=x[--n]; 157 x.size(n); 158 x0.subscribe(home,p,PC_BOOL_VAL,false); 159 return ES_FIX; 160 } 161 // All x-views have been assigned! 162 ViewArray<VY> z(home,y.size()+1); 163 for (int i=0; i<y.size(); i++) 164 z[i]=y[i]; 165 z[y.size()] = x1; 166 GECODE_REWRITE(p,(NaryOrTrue<VY>::post(home(p),z))); 167 } 168 return ES_FIX; 169 } 170 171 template<class VX, class VY> 172 ExecStatus 173 ClauseTrue<VX,VY>::propagate(Space& home, const ModEventDelta&) { 174 if (x0.one() || x1.one()) 175 return home.ES_SUBSUMED(*this); 176 GECODE_ES_CHECK(resubscribe(home,*this,x0,x,x1,y)); 177 GECODE_ES_CHECK(resubscribe(home,*this,x1,y,x0,x)); 178 return ES_FIX; 179 } 180 181 182 /* 183 * Boolean clause propagator (disjunctive) 184 * 185 */ 186 187 /* 188 * Index advisors 189 * 190 */ 191 template<class VX, class VY> 192 forceinline 193 Clause<VX,VY>::Tagged::Tagged(Space& home, Propagator& p, 194 Council<Tagged>& c, bool x0) 195 : Advisor(home,p,c), x(x0) {} 196 197 template<class VX, class VY> 198 forceinline 199 Clause<VX,VY>::Tagged::Tagged(Space& home, Tagged& a) 200 : Advisor(home,a), x(a.x) {} 201 202 template<class VX, class VY> 203 forceinline 204 Clause<VX,VY>::Clause(Home home, ViewArray<VX>& x0, ViewArray<VY>& y0, 205 VX z0) 206 : Propagator(home), x(x0), y(y0), z(z0), n_zero(0), c(home) { 207 x.subscribe(home,*new (home) Tagged(home,*this,c,true)); 208 y.subscribe(home,*new (home) Tagged(home,*this,c,false)); 209 z.subscribe(home,*this,PC_BOOL_VAL); 210 } 211 212 template<class VX, class VY> 213 forceinline 214 Clause<VX,VY>::Clause(Space& home, Clause<VX,VY>& p) 215 : Propagator(home,p), n_zero(p.n_zero) { 216 x.update(home,p.x); 217 y.update(home,p.y); 218 z.update(home,p.z); 219 c.update(home,p.c); 220 } 221 222 template<class VX> 223 forceinline void 224 eliminate_zero(ViewArray<VX>& x, int& n_zero) { 225 if (n_zero > 0) { 226 int n=x.size(); 227 // Eliminate all zeros 228 for (int i=n; i--; ) 229 if (x[i].zero()) { 230 x[i]=x[--n]; n_zero--; 231 } 232 x.size(n); 233 } 234 } 235 236 template<class VX, class VY> 237 Actor* 238 Clause<VX,VY>::copy(Space& home) { 239 eliminate_zero(x,n_zero); 240 eliminate_zero(y,n_zero); 241 return new (home) Clause<VX,VY>(home,*this); 242 } 243 244 template<class VX, class VY> 245 inline ExecStatus 246 Clause<VX,VY>::post(Home home, ViewArray<VX>& x, ViewArray<VY>& y, VX z) { 247 assert(!shared(x) && !shared(y)); 248 if (z.one()) 249 return ClauseTrue<VX,VY>::post(home,x,y); 250 if (z.zero()) { 251 for (int i=0; i<x.size(); i++) 252 GECODE_ME_CHECK(x[i].zero(home)); 253 for (int i=0; i<y.size(); i++) 254 GECODE_ME_CHECK(y[i].zero(home)); 255 return ES_OK; 256 } 257 for (int i=x.size(); i--; ) 258 if (x[i].one()) { 259 GECODE_ME_CHECK(z.one_none(home)); 260 return ES_OK; 261 } else if (x[i].zero()) { 262 x.move_lst(i); 263 } 264 if (x.size() == 0) 265 return NaryOr<VY,VX>::post(home,y,z); 266 for (int i=y.size(); i--; ) 267 if (y[i].one()) { 268 GECODE_ME_CHECK(z.one_none(home)); 269 return ES_OK; 270 } else if (y[i].zero()) { 271 y.move_lst(i); 272 } 273 if (y.size() == 0) 274 return NaryOr<VX,VX>::post(home,x,z); 275 if ((x.size() == 1) && (y.size() == 1)) { 276 return Or<VX,VY,VX>::post(home,x[0],y[0],z); 277 } else if (shared(x,y)) { 278 GECODE_ME_CHECK(z.one_none(home)); 279 } else { 280 (void) new (home) Clause<VX,VY>(home,x,y,z); 281 } 282 return ES_OK; 283 } 284 285 template<class VX, class VY> 286 PropCost 287 Clause<VX,VY>::cost(const Space&, const ModEventDelta&) const { 288 return PropCost::unary(PropCost::LO); 289 } 290 291 template<class VX, class VY> 292 forceinline void 293 Clause<VX,VY>::cancel(Space& home) { 294 for (Advisors<Tagged> as(c); as(); ++as) { 295 if (as.advisor().x) 296 x.cancel(home,as.advisor()); 297 else 298 y.cancel(home,as.advisor()); 299 as.advisor().dispose(home,c); 300 } 301 c.dispose(home); 302 z.cancel(home,*this,PC_BOOL_VAL); 303 } 304 305 template<class VX, class VY> 306 forceinline size_t 307 Clause<VX,VY>::dispose(Space& home) { 308 cancel(home); 309 (void) Propagator::dispose(home); 310 return sizeof(*this); 311 } 312 313 314 template<class VX, class VY> 315 ExecStatus 316 Clause<VX,VY>::advise(Space&, Advisor& _a, const Delta& d) { 317 Tagged& a = static_cast<Tagged&>(_a); 318 // Decides whether the propagator must be run 319 if ((a.x && VX::zero(d)) || (!a.x && VY::zero(d))) 320 if (++n_zero < x.size() + y.size()) 321 return ES_FIX; 322 return ES_NOFIX; 323 } 324 325 template<class VX, class VY> 326 void 327 Clause<VX,VY>::reschedule(Space& home) { 328 z.reschedule(home,*this,PC_BOOL_VAL); 329 if (n_zero == x.size() + y.size()) 330 VX::schedule(home,*this,ME_BOOL_VAL); 331 for (int i=0; i<x.size(); i++) 332 if (x[i].one()) { 333 VX::schedule(home,*this,ME_BOOL_VAL); 334 return; 335 } 336 for (int i=0; i<y.size(); i++) 337 if (y[i].one()) { 338 VX::schedule(home,*this,ME_BOOL_VAL); 339 return; 340 } 341 } 342 343 template<class VX, class VY> 344 ExecStatus 345 Clause<VX,VY>::propagate(Space& home, const ModEventDelta&) { 346 if (z.one()) 347 GECODE_REWRITE(*this,(ClauseTrue<VX,VY>::post(home(*this),x,y))); 348 if (z.zero()) { 349 for (int i=0; i<x.size(); i++) 350 GECODE_ME_CHECK(x[i].zero(home)); 351 for (int i=0; i<y.size(); i++) 352 GECODE_ME_CHECK(y[i].zero(home)); 353 c.dispose(home); 354 } else if (n_zero == x.size() + y.size()) { 355 GECODE_ME_CHECK(z.zero_none(home)); 356 c.dispose(home); 357 } else { 358 // There is at least one view which is one 359 GECODE_ME_CHECK(z.one_none(home)); 360 } 361 return home.ES_SUBSUMED(*this); 362 } 363 364}}} 365 366// STATISTICS: int-prop 367