Generated on Mon May 10 06:46:32 2010 for Gecode by doxygen 1.6.3

dom.hpp

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  *  Contributing authors:
00007  *     Christian Schulte <schulte@gecode.org>
00008  *     Guido Tack <tack@gecode.org>
00009  *
00010  *  Copyright:
00011  *     Patrick Pekczynski, 2004
00012  *     Christian Schulte, 2009
00013  *     Guido Tack, 2009
00014  *
00015  *  Last modified:
00016  *     $Date: 2010-03-03 17:32:21 +0100 (Wed, 03 Mar 2010) $ by $Author: schulte $
00017  *     $Revision: 10364 $
00018  *
00019  *  This file is part of Gecode, the generic constraint
00020  *  development environment:
00021  *     http://www.gecode.org
00022  *
00023  *  Permission is hereby granted, free of charge, to any person obtaining
00024  *  a copy of this software and associated documentation files (the
00025  *  "Software"), to deal in the Software without restriction, including
00026  *  without limitation the rights to use, copy, modify, merge, publish,
00027  *  distribute, sublicense, and/or sell copies of the Software, and to
00028  *  permit persons to whom the Software is furnished to do so, subject to
00029  *  the following conditions:
00030  *
00031  *  The above copyright notice and this permission notice shall be
00032  *  included in all copies or substantial portions of the Software.
00033  *
00034  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00035  *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00036  *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00037  *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
00038  *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
00039  *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
00040  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00041  *
00042  */
00043 
00044 namespace Gecode { namespace Int { namespace GCC {
00045 
00046   /*
00047    * Analogously to "gcc/bnd.hpp" we split the algorithm
00048    * in two parts:
00049    *   1) the UBC (Upper Bound Constraint) stating that there are
00050    *      at most k[i].max() occurences of the value v_i
00051    *   2) the LBC (Lower Bound Constraint) stating that there are
00052    *      at least k[i].min() occurences of the value v_i
00053    *
00054    * The algorithm proceeds in 5 STEPS:
00055    *
00056    * STEP 1:
00057    *    Build the bipartite value-graph G=(<X,D>,E),
00058    *    with X = all variable nodes (each variable forms a node)
00059    *         D = all value nodes (union over all domains of the variables)
00060    *    and (x_i,v) is an edge in G iff value v is in the domain D_i of x_i
00061    *
00062    * STEP 2:   Compute a matching in the value graph.
00063    * STEP 3:   Compute all even alternating paths from unmatched  nodes
00064    * STEP 4:   Compute strongly connected components in the merged graph
00065    * STEP 5:   Update the Domains according to the computed edges
00066    *
00067    */
00068 
00069   template<class Card>
00070   inline
00071   Dom<Card>::Dom(Home home, ViewArray<IntView>& x0,
00072                  ViewArray<Card>& k0, bool cf)
00073     : Propagator(home), x(x0),  y(home, x0),
00074       k(k0), vvg(NULL), card_fixed(cf){
00075     // y is used for bounds propagation since prop_bnd needs all variables
00076     // values within the domain bounds
00077     x.subscribe(home, *this, PC_INT_DOM);
00078     k.subscribe(home, *this, PC_INT_DOM);
00079   }
00080 
00081   template<class Card>
00082   forceinline
00083   Dom<Card>::Dom(Space& home, bool share, Dom<Card>& p)
00084     : Propagator(home, share, p), vvg(NULL), card_fixed(p.card_fixed) {
00085     x.update(home, share, p.x);
00086     y.update(home, share, p.y);
00087     k.update(home, share, p.k);
00088   }
00089 
00090   template<class Card>
00091   forceinline size_t
00092   Dom<Card>::dispose(Space& home) {
00093     x.cancel(home,*this, PC_INT_DOM);
00094     k.cancel(home,*this, PC_INT_DOM);
00095     (void) Propagator::dispose(home);
00096     return sizeof(*this);
00097   }
00098 
00099   template<class Card>
00100   Actor*
00101   Dom<Card>::copy(Space& home, bool share) {
00102     return new (home) Dom<Card>(home, share, *this);
00103   }
00104 
00105   template<class Card>
00106   PropCost
00107   Dom<Card>::cost(const Space&, const ModEventDelta&) const {
00108     return PropCost::cubic(PropCost::LO, x.size());
00109   }
00110 
00111   template<class Card>
00112   ExecStatus
00113   Dom<Card>::propagate(Space& home, const ModEventDelta&) {
00114     Region r(home);
00115 
00116     int* count = r.alloc<int>(k.size());
00117     for (int i = k.size(); i--; )
00118       count[i] = 0;
00119 
00120     // total number of assigned views
00121     int noa = 0;
00122     for (int i = y.size(); i--; )
00123       if (y[i].assigned()) {
00124         noa++;
00125         int idx;
00126         if (!lookupValue(k,y[i].val(),idx))
00127           return ES_FAILED;
00128         count[idx]++;
00129         if (Card::propagate && (k[idx].max() == 0))
00130           return ES_FAILED;
00131       }
00132 
00133     if (noa == y.size()) {
00134       // All views are assigned
00135       for (int i = k.size(); i--; ) {
00136         if ((k[i].min() > count[i]) || (count[i] > k[i].max()))
00137           return ES_FAILED;
00138         // the solution contains ci occurences of value k[i].card();
00139         if (Card::propagate)
00140           GECODE_ME_CHECK(k[i].eq(home, count[i]));
00141       }
00142       return home.ES_SUBSUMED(*this);
00143     }
00144 
00145     // before propagation performs inferences on cardinality variables:
00146     if (Card::propagate) {
00147       if (noa > 0)
00148         for (int i = k.size(); i--; )
00149           if (!k[i].assigned()) {
00150             GECODE_ME_CHECK(k[i].lq(home, y.size() - (noa - count[i])));
00151             GECODE_ME_CHECK(k[i].gq(home, count[i]));
00152           }
00153 
00154       GECODE_ES_CHECK(prop_card<Card>(home,y,k));
00155       if (!card_consistent<Card>(y,k))
00156         return ES_FAILED;
00157     }
00158 
00159     if (x.size() == 0) {
00160       for (int j = k.size(); j--; )
00161         if ((k[j].min() > k[j].counter()) || (k[j].max() < k[j].counter()))
00162           return ES_FAILED;
00163       return home.ES_SUBSUMED(*this);
00164     } else if ((x.size() == 1) && (x[0].assigned())) {
00165       int idx;
00166       if (!lookupValue(k,x[0].val(),idx))
00167         return ES_FAILED;
00168       GECODE_ME_CHECK(k[idx].inc());
00169       for (int j = k.size(); j--; )
00170         if ((k[j].min() > k[j].counter()) || (k[j].max() < k[j].counter()))
00171           return ES_FAILED;
00172       return home.ES_SUBSUMED(*this);
00173     }
00174 
00175     if (vvg == NULL) {
00176       int smin = 0;
00177       int smax = 0;
00178       for (int i=k.size(); i--; )
00179         if (k[i].counter() > k[i].max() ) {
00180           return ES_FAILED;
00181         } else {
00182           smax += (k[i].max() - k[i].counter());
00183           if (k[i].counter() < k[i].min())
00184             smin += (k[i].min() - k[i].counter());
00185         }
00186 
00187       if ((x.size() < smin) || (smax < x.size()))
00188         return ES_FAILED;
00189 
00190       vvg = new (home) VarValGraph<Card>(home, x, k, smin, smax);
00191       GECODE_ES_CHECK(vvg->min_require(home,x,k));
00192       GECODE_ES_CHECK(vvg->template maximum_matching<UBC>(home));
00193       if (!card_fixed)
00194         GECODE_ES_CHECK(vvg->template maximum_matching<LBC>(home));
00195     } else {
00196       GECODE_ES_CHECK(vvg->sync(home,x,k));
00197     }
00198 
00199     vvg->template free_alternating_paths<UBC>(home);
00200     vvg->template strongly_connected_components<UBC>(home);
00201 
00202     GECODE_ES_CHECK(vvg->template narrow<UBC>(home,x,k));
00203 
00204     if (!card_fixed) {
00205       if (Card::propagate)
00206         GECODE_ES_CHECK(vvg->sync(home,x,k));
00207 
00208       vvg->template free_alternating_paths<LBC>(home);
00209       vvg->template strongly_connected_components<LBC>(home);
00210 
00211       GECODE_ES_CHECK(vvg->template narrow<LBC>(home,x,k));
00212     }
00213 
00214     {
00215       bool card_assigned = true;
00216       if (Card::propagate) {
00217         GECODE_ES_CHECK(prop_card<Card>(home, y, k));
00218         
00219         for (int i = k.size(); i--; )
00220           if (!k[i].assigned()) {
00221             card_assigned = false; break;
00222           }
00223       }
00224       
00225       if (card_assigned) {
00226         if (x.size() == 0) {
00227           for (int j=k.size(); j--; )
00228             if ((k[j].min() > k[j].counter()) || 
00229                 (k[j].max() < k[j].counter()))
00230               return ES_FAILED;
00231           return home.ES_SUBSUMED(*this);
00232         } else if ((x.size() == 1) && x[0].assigned()) {
00233           int idx;
00234           if (!lookupValue(k,x[0].val(),idx))
00235             return ES_FAILED;
00236           GECODE_ME_CHECK(k[idx].inc());
00237           
00238           for (int j = k.size(); j--; )
00239             if ((k[j].min() > k[j].counter()) || 
00240                 (k[j].max() < k[j].counter()))
00241               return ES_FAILED;
00242           return home.ES_SUBSUMED(*this);
00243         }
00244       }
00245     }
00246 
00247     for (int i = k.size(); i--; )
00248       count[i] = 0;
00249 
00250     bool all_assigned = true;
00251     // total number of assigned views
00252     for (int i = y.size(); i--; )
00253       if (y[i].assigned()) {
00254         int idx;
00255         if (!lookupValue(k,y[i].val(),idx))
00256           return ES_FAILED;
00257         count[idx]++;
00258         if (Card::propagate && (k[idx].max() == 0))
00259           return ES_FAILED;
00260       } else {
00261         all_assigned = false;
00262       }
00263 
00264     if (Card::propagate)
00265       GECODE_ES_CHECK(prop_card<Card>(home, y, k));
00266 
00267     if (all_assigned) {
00268       for (int i = k.size(); i--; ) {
00269         if ((k[i].min() > count[i]) || (count[i] > k[i].max()))
00270           return ES_FAILED;
00271         // the solution contains count[i] occurences of value k[i].card();
00272         if (Card::propagate)
00273           GECODE_ME_CHECK(k[i].eq(home,count[i]));
00274       }
00275       return home.ES_SUBSUMED(*this);
00276     }
00277 
00278     if (Card::propagate) {
00279       int ysmax = y.size();
00280       for (int i=k.size(); i--; )
00281         ysmax -= k[i].max();
00282       int smax = 0;
00283       bool card_ass = true;
00284       for (int i = k.size(); i--; ) {
00285         GECODE_ME_CHECK(k[i].gq(home, ysmax + k[i].max()));
00286         smax += k[i].max();
00287         GECODE_ME_CHECK(k[i].lq(home, y.size() + k[i].min()));
00288         if (!k[i].assigned())
00289           card_ass = false;
00290       }
00291       if (card_ass && (smax != y.size()))
00292         return ES_FAILED;
00293     }
00294 
00295     return Card::propagate ? ES_NOFIX : ES_FIX;
00296   }
00297 
00298   template<class Card>
00299   inline ExecStatus
00300   Dom<Card>::post(Home home, 
00301                   ViewArray<IntView>& x, ViewArray<Card>& k) {
00302     GECODE_ES_CHECK((postSideConstraints<Card>(home,x,k)));
00303 
00304     if (isDistinct<Card>(home, x, k))
00305       return Distinct::Dom<IntView>::post(home,x);
00306 
00307     bool cardfix = true;
00308     for (int i = k.size(); i--; )
00309       if (!k[i].assigned()) {
00310         cardfix = false; break;
00311       }
00312 
00313     (void) new (home) Dom<Card>(home,x,k,cardfix);
00314     return ES_OK;
00315   }
00316 
00317 }}}
00318 
00319 // STATISTICS: int-prop