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 * Contributing authors: 7 * Mikael Lagerkvist <lagerkvist@gecode.org> 8 * 9 * Copyright: 10 * Christian Schulte, 2006 11 * Mikael Lagerkvist, 2006 12 * 13 * This file is part of Gecode, the generic constraint 14 * development environment: 15 * http://www.gecode.org 16 * 17 * Permission is hereby granted, free of charge, to any person obtaining 18 * a copy of this software and associated documentation files (the 19 * "Software"), to deal in the Software without restriction, including 20 * without limitation the rights to use, copy, modify, merge, publish, 21 * distribute, sublicense, and/or sell copies of the Software, and to 22 * permit persons to whom the Software is furnished to do so, subject to 23 * the following conditions: 24 * 25 * The above copyright notice and this permission notice shall be 26 * included in all copies or substantial portions of the Software. 27 * 28 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 29 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 30 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 31 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 32 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 33 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 34 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 35 * 36 */ 37 38namespace Gecode { namespace Int { namespace Channel { 39 40 /** 41 * \brief Combine view with information for value propagation 42 * 43 */ 44 template<class View> 45 class ValInfo { 46 public: 47 /// The view 48 View view; 49 /// Whether it has been propagated that view is assigned 50 bool a; 51 /// Initialize 52 void init(View x, int n); 53 /// Update during cloning 54 void update(Space& home, ValInfo<View>& vi); 55 /// Check whether propagation for assignment is to be done 56 bool doval(void) const; 57 /// Check whether propagation for domain is to be done 58 bool dodom(void) const; 59 /// Record that view got assigned 60 void assigned(void); 61 /// Record that one value got removed 62 void removed(int i); 63 /// Update the cardinality and bounds information after pruning 64 void done(void); 65 }; 66 67 template<class View> 68 forceinline void 69 ValInfo<View>::init(View x, int) { 70 view = x; a = false; 71 } 72 73 template<class View> 74 forceinline void 75 ValInfo<View>::update(Space& home, ValInfo<View>& vi) { 76 view.update(home,vi.view); a = vi.a; 77 } 78 79 template<class View> 80 forceinline bool 81 ValInfo<View>::doval(void) const { 82 return !a && view.assigned(); 83 } 84 85 template<class View> 86 forceinline bool 87 ValInfo<View>::dodom(void) const { 88 return false; 89 } 90 91 template<class View> 92 forceinline void 93 ValInfo<View>::assigned(void) { 94 a = true; 95 } 96 97 template<class View> 98 forceinline void 99 ValInfo<View>::removed(int) {} 100 101 template<class View> 102 forceinline void 103 ValInfo<View>::done(void) {} 104 105 106 // Propagate assigned views for x 107 template<class View, class Offset, class Info> 108 ExecStatus 109 doprop_val(Space& home, int n, Info* x, Offset& ox, 110 Info* y, Offset& oy, 111 int& n_na, ProcessStack& xa, ProcessStack& ya) { 112 do { 113 int i = xa.pop(); 114 int j = ox(x[i].view).val(); 115 // Assign the y variable to i (or test if already assigned!) 116 { 117 ModEvent me = oy(y[j].view).eq(home,i); 118 if (me_failed(me)) { 119 return ES_FAILED; 120 } 121 // Record that y[j] has been assigned and must be propagated 122 if (me_modified(me)) 123 ya.push(j); 124 } 125 // Prune the value j from all x variables 126 for (int k=0; k<i; k++) { 127 ModEvent me = ox(x[k].view).nq(home,j); 128 if (me_failed(me)) { 129 return ES_FAILED; 130 } 131 if (me_modified(me)) { 132 if (me == ME_INT_VAL) { 133 // Record that x[k] has been assigned and must be propagated 134 xa.push(k); 135 } else { 136 // One value has been removed and this removal does not need 137 // to be propagated again: after all y[j] = i, so it holds 138 // that y[j] != k. 139 x[k].removed(j); 140 } 141 } 142 } 143 // The same for the other views 144 for (int k=i+1; k<n; k++) { 145 ModEvent me = ox(x[k].view).nq(home,j); 146 if (me_failed(me)) { 147 return ES_FAILED; 148 } 149 if (me_modified(me)) { 150 if (me == ME_INT_VAL) { 151 // Record that x[k] has been assigned and must be propagated 152 xa.push(k); 153 } else { 154 // One value has been removed and this removal does not need 155 // to be propagated again: after all y[j] = i, so it holds 156 // that y[j] != k. 157 x[k].removed(j); 158 } 159 } 160 } 161 x[i].assigned(); n_na--; 162 } while (!xa.empty()); 163 return ES_OK; 164 } 165 166 // Just do a test whether a call to the routine is necessary 167 template<class View, class Offset, class Info> 168 forceinline ExecStatus 169 prop_val(Space& home, int n, Info* x, Offset& ox, Info* y, Offset& oy, 170 int& n_na, ProcessStack& xa, ProcessStack& ya) { 171 if (xa.empty()) 172 return ES_OK; 173 return doprop_val<View,Offset,Info>(home,n,x,ox,y,oy,n_na,xa,ya); 174 } 175 176 /* 177 * The actual propagator 178 * 179 */ 180 template<class View, class Offset, bool shared> 181 forceinline 182 Val<View,Offset,shared>::Val(Home home, int n, ValInfo<View>* xy, 183 Offset& ox, Offset& oy) 184 : Base<ValInfo<View>,Offset,PC_INT_VAL>(home,n,xy,ox,oy) {} 185 186 template<class View, class Offset, bool shared> 187 forceinline 188 Val<View,Offset,shared>::Val(Space& home, Val<View,Offset,shared>& p) 189 : Base<ValInfo<View>,Offset,PC_INT_VAL>(home,p) {} 190 191 template<class View, class Offset, bool shared> 192 Actor* 193 Val<View,Offset,shared>::copy(Space& home) { 194 return new (home) Val<View,Offset,shared>(home,*this); 195 } 196 197 template<class View, class Offset, bool shared> 198 ExecStatus 199 Val<View,Offset,shared>::propagate(Space& home, const ModEventDelta&) { 200 Region r; 201 ProcessStack xa(r,n); 202 ProcessStack ya(r,n); 203 204 ValInfo<View>* x = xy; 205 ValInfo<View>* y = xy+n; 206 207 // Scan x and y for assigned but not yet propagated views 208 for (int i=0; i<n; i++) { 209 if (x[i].doval()) xa.push(i); 210 if (y[i].doval()) ya.push(i); 211 } 212 213 do { 214 // Propagate assigned views for x 215 GECODE_ES_CHECK((prop_val<View,Offset,ValInfo<View> > 216 (home,n,x,ox,y,oy,n_na,xa,ya))); 217 // Propagate assigned views for y 218 GECODE_ES_CHECK((prop_val<View,Offset,ValInfo<View> > 219 (home,n,y,oy,x,ox,n_na,ya,xa))); 220 assert(ya.empty()); 221 } while (!xa.empty()); 222 223 if (n_na == 0) 224 return home.ES_SUBSUMED(*this); 225 return shared ? ES_NOFIX : ES_FIX; 226 } 227 228 template<class View, class Offset, bool shared> 229 ExecStatus 230 Val<View,Offset,shared>::post(Home home, int n, ValInfo<View>* xy, 231 Offset& ox, Offset& oy) { 232 assert(n > 0); 233 if (n == 1) { 234 GECODE_ME_CHECK(ox(xy[0].view).eq(home,0)); 235 GECODE_ME_CHECK(oy(xy[1].view).eq(home,0)); 236 return ES_OK; 237 } 238 for (int i=0; i<n; i++) { 239 GECODE_ME_CHECK(ox(xy[i ].view).gq(home,0)); 240 GECODE_ME_CHECK(ox(xy[i ].view).le(home,n)); 241 GECODE_ME_CHECK(oy(xy[i+n].view).gq(home,0)); 242 GECODE_ME_CHECK(oy(xy[i+n].view).le(home,n)); 243 } 244 (void) new (home) Val<View,Offset,shared>(home,n,xy,ox,oy); 245 return ES_OK; 246 } 247 248}}} 249 250// STATISTICS: int-prop 251