Generated on Wed Nov 1 15:04:33 2006 for Gecode by doxygen 1.4.5

distinct.cc

Go to the documentation of this file.
00001 /*
00002  *  Main authors:
00003  *     Guido Tack <tack@gecode.org>
00004  *
00005  *  Copyright:
00006  *     Guido Tack, 2004
00007  *
00008  *  Last modified:
00009  *     $Date: 2006-04-11 15:58:37 +0200 (Tue, 11 Apr 2006) $ by $Author: tack $
00010  *     $Revision: 3188 $
00011  *
00012  *  This file is part of Gecode, the generic constraint
00013  *  development environment:
00014  *     http://www.gecode.org
00015  *
00016  *  See the file "LICENSE" for information on usage and
00017  *  redistribution of this file, and for a
00018  *     DISCLAIMER OF ALL WARRANTIES.
00019  *
00020  */
00021 
00022 #include "gecode/set.hh"
00023 #include "gecode/set/distinct.hh"
00024 
00025 /*
00026  * These propagators implement the scheme discussed in
00027  *
00028  * Andrew Sadler and Carment Gervet: Global Reasoning on Sets.
00029  * FORMUL'01 workshop in conjunction with CP 2001.
00030  *
00031  * Todo: make the propagators incremental.
00032  */
00033 
00034 namespace Gecode { namespace Set { namespace Distinct {
00035 
00036   /*
00037    * n-ary distinct with fixed cardinalities propagator
00038    *
00039    */
00040 
00041   static ModEvent
00042   nosubset(Space* home, SetView x, SetView y) {
00043     GlbRanges<SetView> xglb(x);
00044     GlbRanges<SetView> yglb(y);
00045     Iter::Ranges::Diff<GlbRanges<SetView>, GlbRanges<SetView> >
00046       diff(xglb, yglb);
00047     if (!diff())
00048       return ME_SET_FAILED;
00049     if (diff.min() != diff.max())
00050       return ME_SET_NONE;
00051     int a = diff.min();
00052     ++diff;
00053     if (diff())
00054       return ME_SET_NONE;
00055     return y.exclude(home, a);
00056   }
00057 
00058   Actor*
00059   Distinct::copy(Space* home, bool share) {
00060     return new (home) Distinct(home,share,*this);
00061   }
00062 
00063   ExecStatus
00064   Distinct::propagate(Space* home) {
00065 
00066     int curClique = x.size();
00067     int oldCliques = curClique;
00068 
00069     while (curClique>1) {
00070       
00071       unsigned int li = x[0].glbSize();
00072       curClique--;
00073       SetView tmp = x[curClique];
00074       x[curClique] = x[0];
00075       x[0] = tmp;
00076 
00077       GECODE_AUTOARRAY(LubRanges<SetView>, cliqueLubs, oldCliques);
00078       cliqueLubs[0].init(x[curClique]);
00079       unsigned int ki = 1; // size of the clique
00080 
00081       // Find the clique of x[i], i.e. all sets with the same glb.
00082       // The clique will be moved to the end of the array, but before
00083       // oldCliques.
00084       for (int j=0; j<curClique; ) {
00085         GlbRanges<SetView> xjglb(x[j]);
00086         GlbRanges<SetView> xiglb(x[curClique]);
00087         if (Iter::Ranges::equal(xiglb, xjglb)) {
00088           curClique--;
00089           SetView tmp2 = x[curClique];
00090           x[curClique] = x[j];
00091           x[j] = tmp2;
00092           cliqueLubs[ki].init(x[curClique]);
00093           ki++;
00094         } else {
00095           j++;
00096         }
00097       }
00098 
00099       Iter::Ranges::NaryUnion<LubRanges<SetView> > cliqueLub(cliqueLubs, ki);
00100       unsigned int ui = Iter::Ranges::size(cliqueLub);
00101 
00102       unsigned int possible = bin.c(ui-li, c-li);
00103 
00104       if (possible < ki)
00105         return ES_FAILED;
00106 
00107       if (possible == ki) {
00108         for (int i=curClique; i--; ) {
00109           GECODE_ME_CHECK(nosubset(home, x[curClique], x[i]));
00110         }
00111         for (int i=oldCliques; i<x.size(); i++) {
00112           GECODE_ME_CHECK(nosubset(home, x[curClique], x[i]));
00113         }
00114       }
00115 
00116       oldCliques = curClique;
00117     }
00118 
00119     return ES_NOFIX;
00120   }
00121 
00122 }}}
00123 
00124 // STATISTICS: set-prop