Generated on Mon Aug 25 11:35:33 2008 for Gecode by doxygen 1.5.6

partition.cc

Go to the documentation of this file.
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, 2006
00008  *
00009  *  Last modified:
00010  *     $Date: 2008-02-01 14:48:35 +0100 (Fri, 01 Feb 2008) $ by $Author: tack $
00011  *     $Revision: 6039 $
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 #include "gecode/cpltset.hh"
00039 #include "gecode/cpltset/propagators.hh"
00040 
00041 using namespace Gecode::CpltSet;
00042 
00043 namespace Gecode {
00044 
00045   namespace CpltSet { namespace Partition {
00046 
00052     template <class View>
00053     void build_partition(ViewArray<View>& x, bdd& d0) {
00054       // make it more readable
00055       typedef Set::LubRanges<View> SetLub;
00056       namespace IR = Iter::Ranges;
00057 
00058       // disjoint
00059       int n = x.size();
00060       for (int i = 0; i < n - 1; i++) {
00061         for (int j = i + 1; j < n; j++) {
00062           SetLub lubx(x[i]);
00063           SetLub luby(x[j]);
00064           IR::Inter<SetLub, SetLub> inter(lubx, luby);
00065           IR::ToValues<IR::Inter<SetLub, SetLub> > values(inter);
00066           IR::ValCache<IR::ToValues<IR::Inter<SetLub, SetLub> > > 
00067             cache(values);
00068 
00069           for (cache.last(); cache(); --cache) {
00070             int ximin = x[i].initialLubMin();
00071             int xjmin = x[j].initialLubMin();
00072             int v = cache.min();
00073             d0 &= !(x[i].element(v - ximin) & x[j].element(v - xjmin));
00074           }
00075         }
00076       }
00077 
00078       unsigned int xtab = x[0].tableWidth();  
00079       for (int i = n; i--;) {
00080         if (x[i].tableWidth() > xtab)
00081           xtab = x[i].tableWidth();
00082       }
00083 
00084       // just state that the union of all sets is us
00085       // iff all the variables have the same initial minimum and maximum
00086       for (unsigned int k = 0; k < xtab; k++) {
00087         bdd c0 = bdd_false();
00088         for (int i = 0; i < n; i++) {
00089           if (k < x[i].tableWidth())
00090             c0 |= x[i].element(k);
00091         }
00092         d0 &= (c0  % bdd_true());
00093       }
00094     }
00095 
00096     template <class View0, class View1>
00097     void build_partition(ViewArray<View0>& x, View1& y, bdd& d0) {
00098       // make it more readable
00099       typedef Set::LubRanges<View0> SetLub;
00100       namespace IR = Iter::Ranges;
00101 
00102       // disjoint
00103       int n = x.size();
00104       for (int i = 0; i < n - 1; i++) {
00105         for (int j = i + 1; j < n; j++) {
00106           SetLub lubx(x[i]);
00107           SetLub luby(x[j]);
00108           IR::Inter<SetLub, SetLub> inter(lubx, luby);
00109           IR::ToValues<IR::Inter<SetLub, SetLub> > values(inter);
00110           IR::ValCache<IR::ToValues<IR::Inter<SetLub, SetLub> > > 
00111             cache(values);
00112 
00113           for (cache.last(); cache(); --cache) {
00114             int ximin = x[i].initialLubMin();
00115             int xjmin = x[j].initialLubMin();
00116             int v = cache.min();
00117             d0 &= !(x[i].element(v - ximin) & x[j].element(v - xjmin));
00118           }
00119         }
00120       }
00121 
00122       unsigned int ytab = y.tableWidth();
00123       int ymin = y.initialLubMin();
00124       for (unsigned int k = 0; k < ytab; k++) {
00125         bdd c0 = bdd_false();
00126         for (int i = 0; i < n; i++) {
00127           int xmin = x[i].initialLubMin();
00128           int xmax = x[i].initialLubMax();
00129           int shift = std::max(ymin, xmin) - std::min(xmin, ymin);
00130           if (xmin <= ymin + (int) k && ymin + (int) k <= xmax) {
00131             c0 |= x[i].element(k - shift);
00132           }
00133         }
00134         d0 &= (c0  % y.element(k));
00135       }
00136     }
00137 
00138     template <class View>
00139     void build_lexorder(ViewArray<View>& x, bdd& d0, CpltSetRelType lex) {
00140 
00141       int n = x.size();
00142       unsigned int xtab = x[0].tableWidth();  
00143 
00144       for (int i = n; i--;) 
00145         if (x[i].tableWidth() > xtab)
00146           xtab = x[i].tableWidth();
00147 
00148       // std::cerr << "with lex \n";
00149       for (int i = 0; i < n - 1; i++) {
00150         for (int j = i + 1; j < n; j++) {
00151           unsigned int xai_off = x[i].offset();
00152           unsigned int xaj_off = x[j].offset();
00153           switch (lex) {
00154           case SRT_LE: 
00155             {
00156               d0 &= lexlt(xai_off, xaj_off, xtab, xtab - 1);
00157               break;
00158             }
00159           case SRT_GR: 
00160             {
00161               d0 &= lexlt(xaj_off, xai_off, xtab, xtab - 1);
00162               break;
00163             }
00164           case SRT_LQ: 
00165             {
00166               d0 &= lexlq(xai_off, xaj_off, xtab, xtab - 1);
00167               break;
00168             }
00169           case SRT_GQ: 
00170             {
00171               d0 &= lexlq(xaj_off, xai_off, xtab, xtab - 1);
00172               break;
00173             }
00174           case SRT_LE_REV: 
00175             {
00176               d0 &= lexltrev(xai_off, xaj_off, xtab, 0);
00177               break;
00178             }
00179           case SRT_GR_REV: 
00180             {
00181               d0 &= lexltrev(xaj_off, xai_off, xtab, 0);
00182               break;
00183             }
00184           case SRT_LQ_REV: 
00185             {
00186               d0 &= lexlqrev(xai_off, xaj_off, xtab, 0);
00187               break;
00188             }
00189           case SRT_GQ_REV: 
00190             {
00191               d0 &= lexlqrev(xaj_off, xai_off, xtab, 0);
00192               break;
00193             }
00194           default:
00195             {
00196               throw
00197                 CpltSet::InvalidRelation("partition rel not implemented");
00198               break;
00199             }
00200           }
00201         }
00202       }
00203     }
00204 
00205     template <class View>
00206     void partition_post(Space* home, ViewArray<View>& x, bool withlex, 
00207                         CpltSetRelType lex, bool withcard, int d) {
00208 
00209       if (home->failed()) return;
00210 
00211       int n = x.size();
00212 
00213       bdd d0 = bdd_true();     
00214       build_partition(x, d0);
00215 
00216       // forall i: x_{i - 1} \prec_{lex_{bit}} x_i
00217       if (withlex) 
00218         build_lexorder(x, d0, lex);
00219 
00220       if (withcard) {
00221         for (int i = n; i--; ) {
00222           unsigned int off   = x[i].offset();
00223           unsigned int range = x[i].tableWidth();
00224           d0 &= cardcheck(range, off, d, d);
00225         }
00226       }
00227 
00228       GECODE_ES_FAIL(home, NaryCpltSetPropagator<View>::post(home, x, d0));
00229     }
00230 
00231     template <class View>
00232     void partition_post(Space* home, ViewArray<View>& x, View& y, 
00233                         bool, SetRelType, bool, int) {
00234       if (home->failed()) return;
00235 
00236       int n = x.size();
00237 
00238       bdd d0 = bdd_true();     
00239       build_partition(x, y, d0);
00240 
00241       ViewArray<View> naryone(home, x.size() + 1);
00242       for (int i = 0; i < n; i++) 
00243         naryone[i] = x[i]; 
00244       naryone[n] = y;
00245 
00246       GECODE_ES_FAIL(home,
00247         NaryCpltSetPropagator<View>::post(home, naryone, d0));
00248     }
00249 
00250     template <class View0, class View1>
00251     void partition_post(Space* home, ViewArray<View0>& x, View1& y, 
00252                         bool withlex, SetRelType lex, 
00253                         bool withcard, int d) {
00254       if (home->failed()) return;
00255 
00256       bdd d0 = bdd_true();     
00257       build_partition(x, y, d0);
00258 
00259       GECODE_ES_FAIL(home,
00260         (NaryOneCpltSetPropagator<View0, View1>::post(home, x, y, d0)));
00261     }
00262 
00263     template <class View>
00264     void partition_post(Space* home, ViewArray<View>& x, bool,
00265                         SetRelType, bool withcard, int d) {
00266       if (home->failed()) return;
00267 
00268       int n = x.size();
00269 
00270       int minx = x[0].initialLubMin();
00271       int maxx = x[0].initialLubMax(); 
00272       unsigned int xtab = x[0].tableWidth();  
00273       for (int i = n; i--;) {
00274         if (x[i].initialLubMin() < minx) {
00275           minx = x[i].initialLubMin();
00276         }
00277         if (x[i].initialLubMax() > maxx) {
00278           maxx = x[i].initialLubMax();
00279         }
00280         if (x[i].tableWidth() > xtab) {
00281           xtab = x[i].tableWidth();
00282         }
00283       }
00284 
00285       // build partition
00286       bdd d0 = bdd_true();     
00287 
00288       for (int i = 0; i < n - 1; i++) {
00289         for (int j = i + 1; j < n; j++) {
00290           Set::LubRanges<View> lubx(x[i]);
00291           Set::LubRanges<View> luby(x[j]);
00292           Gecode::Iter::Ranges::Inter<Set::LubRanges<View>, 
00293             Set::LubRanges<View> > inter(lubx, luby);
00294           Gecode::Iter::Ranges::ToValues<
00295             Gecode::Iter::Ranges::Inter<Set::LubRanges<View>, 
00296               Set::LubRanges<View> > > values(inter);
00297           Gecode::Iter::Ranges::ValCache<
00298             Gecode::Iter::Ranges::ToValues<
00299                 Gecode::Iter::Ranges::Inter<Set::LubRanges<View>, 
00300                   Set::LubRanges<View> > > > cache(values);
00301           cache.last();
00302           for (; cache(); --cache) {
00303             int ximin = x[i].initialLubMin();
00304             int xjmin = x[j].initialLubMin();
00305             int v = cache.min();
00306             d0 &= !(x[i].element(v - ximin) & x[j].element(v - xjmin));
00307           }
00308 
00309         }
00310       }
00311 
00312       // no lex ordering
00313 
00314       // just state that the union of all sets is us
00315       for (unsigned int k = 0; k < xtab; k++) {
00316         bdd c0 = bdd_false();
00317         for (int i = 0; i < n; i++) {
00318           if (k < x[i].tableWidth()) {
00319             c0 |= x[i].element(k);
00320           }
00321         }
00322         d0 &= (c0  % bdd_true());
00323       }
00324 
00325       if (withcard) {
00326         for (int i = n; i--; ) {
00327           unsigned int off   = x[i].offset();
00328           unsigned int range = x[i].tableWidth();
00329           d0 &= cardcheck(range, off, d, d);
00330         }
00331       }
00332 
00333       GECODE_ES_FAIL(home, NaryCpltSetPropagator<View>::post(home, x, d0));
00334     }
00335 
00336     template <class Rel>
00337     forceinline void 
00338     partition_con(Space* home, const CpltSetVarArgs& x, bool withlex, Rel lex, 
00339                   bool withcard, int d) {
00340       ViewArray<CpltSetView> bv(home, x);
00341       partition_post(home, bv, withlex, lex, withcard, d);
00342     }
00343 
00344     // For testing purposes only supported for bddviews
00345     template <class Rel>
00346     forceinline void 
00347     partition_con(Space* home, const CpltSetVarArgs& x, const CpltSetVar& y, 
00348                   bool withlex, Rel lex, bool withcard, int d) {
00349       ViewArray<CpltSetView> bv(home, x);
00350       CpltSetView yv(y);
00351       partition_post(home, bv, yv, withlex, lex, withcard, d);
00352     }
00353     
00354   }} // end namespace CpltSet::Partition
00355 
00356   using namespace CpltSet::Partition;
00357 
00358   void partition(Space* home, const CpltSetVarArgs& x) {
00359     partition_con(home, x, false, SRT_EQ, false, -1);
00360   }
00361 
00362   void partition(Space* home, const CpltSetVarArgs& x, const CpltSetVar& y) {
00363     partition_con(home, x, y, false, SRT_EQ, false, -1);
00364   }
00365 
00366   void partitionLex(Space* home, const CpltSetVarArgs& x,
00367                     CpltSetRelType lex) {
00368     partition_con(home, x, true, lex, false, -1);
00369   }
00370 
00371   void partitionLexCard(Space* home, const CpltSetVarArgs& x,
00372                         CpltSetRelType lex, unsigned int c) {
00373     Set::Limits::check(c, "CpltSet::partitionLexCard");
00374     partition_con(home, x, true, lex, true, c);
00375   }
00376 
00377   void partitionCard(Space* home, const CpltSetVarArgs& x, unsigned int c) {
00378     Set::Limits::check(c, "CpltSet::partitionCard");
00379     partition_con(home, x, false, SRT_EQ, true, c);
00380   }
00381 }
00382 
00383 // STATISTICS: cpltset-post