gecode » int » sorted

00001 /* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */ 00002 /* 00003 * Main authors: 00004 * Patrick Pekczynski <pekczynski@ps.uni-sb.de> 00005 * 00006 * Copyright: 00007 * Patrick Pekczynski, 2004 00008 * 00009 * Last modified: 00010 * $Date: 2009-09-08 21:10:29 +0200 (Tue, 08 Sep 2009) $ by $Author: schulte $ 00011 * $Revision: 9692 $ 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 namespace Gecode { namespace Int { namespace Sorted { 00039 00043 class Rank { 00044 public: 00046 int min; 00048 int max; 00049 }; 00050 00057 class SccComponent { 00058 public: 00060 int leftmost; 00062 int left; 00064 int right; 00066 int rightmost; 00067 }; 00068 00080 template<class View, bool Perm> 00081 inline bool 00082 check_subsumption(ViewArray<View>& x, ViewArray<View>& y, ViewArray<View>& z, 00083 bool& subsumed, int& dropfst) { 00084 00085 dropfst = 0; 00086 subsumed = true; 00087 int xs = x.size(); 00088 for (int i = 0; i < xs ; i++) { 00089 if (Perm) { 00090 subsumed &= (x[i].assigned() && 00091 z[i].assigned() && 00092 y[z[i].val()].assigned()); 00093 if (subsumed) { 00094 if (x[i].val() != y[z[i].val()].val()) { 00095 return false; 00096 } else { 00097 if (z[i].val() == i) { 00098 dropfst++; 00099 } 00100 } 00101 } 00102 } else { 00103 subsumed &= (x[i].assigned() && y[i].assigned()); 00104 if (subsumed) { 00105 if (x[i].val() != y[i].val()) { 00106 return false; 00107 } else { 00108 dropfst++; 00109 } 00110 } 00111 } 00112 } 00113 return true; 00114 } 00115 00121 class OfflineMinItem { 00122 public: 00124 int root; 00126 int parent; 00128 int rank; 00130 int name; 00138 int iset; 00140 int succ; 00142 int pred; 00143 }; 00144 00150 class OfflineMin { 00151 private: 00152 OfflineMinItem* sequence; 00153 int* vertices; 00154 int n; 00155 public: 00156 OfflineMin(void); 00157 OfflineMin(OfflineMinItem[], int[], int); 00162 int find(int x); 00167 int find_pc(int x); 00169 void unite(int a, int b, int c); 00171 void makeset(void); 00173 int size(void); 00174 OfflineMinItem& operator [](int); 00175 }; 00176 00177 OfflineMin::OfflineMin(void){ 00178 n = 0; 00179 sequence = NULL; 00180 vertices = NULL; 00181 } 00182 00183 OfflineMin::OfflineMin(OfflineMinItem s[], int v[], int size){ 00184 n = size; 00185 sequence = &s[0]; 00186 vertices = &v[0]; 00187 } 00188 00189 forceinline int 00190 OfflineMin::find(int x) { 00191 while (sequence[x].parent != x) { 00192 x = sequence[x].parent; 00193 } 00194 // x is now the root of the tree 00195 // return the set, x belongs to 00196 return sequence[x].name; 00197 } 00198 00199 forceinline int 00200 OfflineMin::find_pc(int x){ 00201 int vsize = 0; 00202 while (sequence[x].parent != x) { 00203 vertices[x] = x; 00204 x = sequence[x].parent; 00205 } 00206 // x is now the root of the tree 00207 for (int i = vsize; i--; ) { 00208 sequence[vertices[i]].parent = x; 00209 } 00210 // return the set, x belongs to 00211 return sequence[x].name; 00212 } 00213 00214 forceinline void 00215 OfflineMin::unite(int a, int b, int c){ 00216 // c is the union of a and b 00217 int ra = sequence[a].root; 00218 int rb = sequence[b].root; 00219 int large = rb; 00220 int small = ra; 00221 if (sequence[ra].rank > sequence[rb].rank) { 00222 large = ra; 00223 small = rb; 00224 } 00225 sequence[small].parent = large; 00226 sequence[large].rank += sequence[small].rank; 00227 sequence[large].name = c; 00228 sequence[c].root = large; 00229 } 00230 00231 forceinline void 00232 OfflineMin::makeset(void){ 00233 for(int i = n; i--; ){ 00234 OfflineMinItem& cur = sequence[i]; 00235 cur.rank = 0; // initially each set is empty 00236 cur.name = i; // it has its own name 00237 cur.root = i; // it is the root node 00238 cur.parent = i; // it is its own parent 00239 cur.pred = i - 1; 00240 cur.succ = i + 1; 00241 cur.iset = -5; 00242 } 00243 } 00244 00245 forceinline int 00246 OfflineMin::size(void){ 00247 return n; 00248 } 00249 00250 forceinline OfflineMinItem& 00251 OfflineMin::operator [](int i){ 00252 return sequence[i]; 00253 } 00254 00264 template<class View> 00265 class TupleMaxInc { 00266 protected: 00267 ViewArray<View> x; 00268 public: 00269 TupleMaxInc(const ViewArray<View>& x0) : x(x0) {} 00270 bool operator ()(const int i, const int j) { 00271 if (x[i].max() == x[j].max()) { 00272 return x[i].min() < x[j].min(); 00273 } else { 00274 return x[i].max() < x[j].max(); 00275 } 00276 } 00277 }; 00278 00279 00289 template<class View> 00290 class TupleMaxIncExt { 00291 protected: 00292 ViewArray<View> x; 00293 ViewArray<View> z; 00294 public: 00295 TupleMaxIncExt(const ViewArray<View>& x0, 00296 const ViewArray<View>& z0) : x(x0), z(z0) {} 00297 bool operator ()(const int i, const int j) { 00298 if (x[i].max() == x[j].max()) { 00299 if (x[i].min() == x[j].min()) { 00300 if (z[i].max() == z[j].max()) { 00301 return z[i].min() < z[j].min(); 00302 } else { 00303 return z[i].max() < z[j].max(); 00304 } 00305 } else { 00306 return x[i].min() < x[j].min(); 00307 } 00308 } else { 00309 return x[i].max() < x[j].max(); 00310 } 00311 } 00312 }; 00313 00323 template<class View> 00324 class TupleMinInc { 00325 public: 00326 bool operator ()(const View& x, const View& y) { 00327 if (x.min() == y.min()) { 00328 return x.max() < y.max(); 00329 } else { 00330 return x.min() < y.min(); 00331 } 00332 } 00333 }; 00334 00346 template<class View> 00347 class ViewPair { 00348 public: 00349 View x; 00350 View z; 00351 }; 00352 00353 template<class View> 00354 class TupleMinIncExt { 00355 public: 00356 bool operator ()(const ViewPair<View>& x, const ViewPair<View>& y) { 00357 if (x.x.min() == y.x.min()) { 00358 if (x.x.max() == y.x.max()) { 00359 if (x.z.min() == y.z.min()) { 00360 return x.z.max() < y.z.max(); 00361 } else { 00362 return x.z.min() < y.z.min(); 00363 } 00364 } else { 00365 return x.x.max() < y.x.max(); 00366 } 00367 } else { 00368 return x.x.min() < y.x.min(); 00369 } 00370 } 00371 }; 00372 00380 template<class View, bool Perm> 00381 inline bool 00382 array_assigned(Space& home, 00383 ViewArray<View>& x, 00384 ViewArray<View>& y, 00385 ViewArray<View>& z, 00386 bool& subsumed, 00387 bool& match_fixed, 00388 bool&, 00389 bool& noperm_bc) { 00390 00391 bool x_complete = true; 00392 bool y_complete = true; 00393 bool z_complete = true; 00394 00395 for (int i = y.size(); i--; ) { 00396 x_complete &= x[i].assigned(); 00397 y_complete &= y[i].assigned(); 00398 if (Perm) { 00399 z_complete &= z[i].assigned(); 00400 } 00401 } 00402 00403 if (x_complete) { 00404 for (int i = x.size(); i--; ) { 00405 ModEvent me = y[i].eq(home, x[i].val()); 00406 if (me_failed(me)) { 00407 return false; 00408 } 00409 } 00410 if (Perm) { 00411 subsumed = false; 00412 } else { 00413 subsumed = true; 00414 } 00415 } 00416 00417 if (y_complete) { 00418 bool y_equality = true; 00419 for (int i = y.size() - 1; i--; ) { 00420 y_equality &= (y[i].val() == y[i + 1].val()); 00421 } 00422 if (y_equality) { 00423 for (int i = x.size(); i--; ) { 00424 ModEvent me = x[i].eq(home, y[i].val()); 00425 if (me_failed(me)) { 00426 return false; 00427 } 00428 } 00429 if (Perm) { 00430 subsumed = false; 00431 } else { 00432 subsumed = true; 00433 } 00434 noperm_bc = true; 00435 } 00436 } 00437 00438 if (Perm) { 00439 if (z_complete) { 00440 if (x_complete) { 00441 for (int i = x.size(); i--; ) { 00442 ModEvent me = y[z[i].val()].eq(home, x[i].val()); 00443 if (me_failed(me)) { 00444 return false; 00445 } 00446 } 00447 subsumed = true; 00448 return subsumed; 00449 } 00450 if (y_complete) { 00451 for (int i = x.size(); i--; ) { 00452 ModEvent me = x[i].eq(home, y[z[i].val()].val()); 00453 if (me_failed(me)) { 00454 return false; 00455 } 00456 } 00457 subsumed = true; 00458 return subsumed; 00459 } 00460 00461 // validate the permutation 00462 int sum = 0; 00463 for (int i = x.size(); i--; ) { 00464 int pi = z[i].val(); 00465 if (x[i].max() < y[pi].min() || 00466 x[i].min() > y[pi].max()) { 00467 return false; 00468 } 00469 sum += pi; 00470 } 00471 int n = x.size(); 00472 int gauss = ( (n * (n + 1)) / 2); 00473 // if the sum over all assigned permutation variables is not 00474 // equal to the gaussian sum - n they are not distinct, hence invalid 00475 if (sum != gauss - n) { 00476 return false; 00477 } 00478 match_fixed = true; 00479 } 00480 } 00481 return true; 00482 } 00483 00491 template<class View> 00492 forceinline bool 00493 channel(Space& home, ViewArray<View>& x, ViewArray<View>& y, 00494 ViewArray<View>& z, bool& nofix) { 00495 int n = x.size(); 00496 for (int i = n; i--; ) { 00497 if (z[i].assigned()) { 00498 int v = z[i].val(); 00499 if (x[i].assigned()) { 00500 // channel equality from x to y 00501 ModEvent me = y[v].eq(home, x[i].val()); 00502 if (me_failed(me)) 00503 return false; 00504 nofix |= me_modified(me); 00505 } else { 00506 if (y[v].assigned()) { 00507 // channel equality from y to x 00508 ModEvent me = x[i].eq(home, y[v].val()); 00509 if (me_failed(me)) 00510 return false; 00511 nofix |= me_modified(me); 00512 } else { 00513 // constrain upper bound 00514 ModEvent me = x[i].lq(home, y[v].max()); 00515 if (me_failed(me)) 00516 return false; 00517 nofix |= me_modified(me); 00518 00519 // constrain lower bound 00520 me = x[i].gq(home, y[v].min()); 00521 if (me_failed(me)) 00522 return false; 00523 nofix |= me_modified(me); 00524 00525 // constrain the sorted variable 00526 // constrain upper bound 00527 me = y[v].lq(home, x[i].max()); 00528 if (me_failed(me)) 00529 return false; 00530 nofix |= me_modified(me); 00531 00532 // constrain lower bound 00533 me = y[v].gq(home, x[i].min()); 00534 if (me_failed(me)) 00535 return false; 00536 nofix |= me_modified(me); 00537 } 00538 } 00539 } else { 00540 // if the permutation variable is undetermined 00541 int l = z[i].min(); 00542 int r = z[i].max(); 00543 // upper bound 00544 ModEvent me = x[i].lq(home, y[r].max()); 00545 if (me_failed(me)) 00546 return false; 00547 nofix |= me_modified(me); 00548 00549 // lower bound 00550 me = x[i].gq(home, y[l].min()); 00551 if (me_failed(me)) 00552 return false; 00553 nofix |= me_modified(me); 00554 } 00555 } 00556 return true; 00557 } 00558 00559 00560 }}} 00561 00562 00563 // STATISTICS: int-prop