Generated on Mon Jul 6 18:09:06 2009 for Gecode by doxygen 1.5.9

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  *  Copyright:
00007  *     Patrick Pekczynski, 2004
00008  *
00009  *  Last modified:
00010  *     $Date: 2009-02-03 11:13:22 +0100 (Tue, 03 Feb 2009) $
00011        $Author: schulte $
00012  *     $Revision: 8129 $
00013  *
00014  *  This file is part of Gecode, the generic constraint
00015  *  development environment:
00016  *     http://www.gecode.org
00017  *
00018  *  Permission is hereby granted, free of charge, to any person obtaining
00019  *  a copy of this software and associated documentation files (the
00020  *  "Software"), to deal in the Software without restriction, including
00021  *  without limitation the rights to use, copy, modify, merge, publish,
00022  *  distribute, sublicense, and/or sell copies of the Software, and to
00023  *  permit persons to whom the Software is furnished to do so, subject to
00024  *  the following conditions:
00025  *
00026  *  The above copyright notice and this permission notice shall be
00027  *  included in all copies or substantial portions of the Software.
00028  *
00029  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00030  *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00031  *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00032  *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
00033  *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
00034  *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
00035  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00036  *
00037  */
00038 
00039 namespace Gecode { namespace Int { namespace GCC {
00040 
00041   /*
00042    * Analogously to "gcc/bnd.hpp" we split the algorithm
00043    * in two parts:
00044    *   1) the UBC (Upper Bound Constraint) stating that there are
00045    *      at most k[i].max() occurences of the value v_i
00046    *   2) the LBC (Lower Bound Constraint) stating that there are
00047    *      at least k[i].min() occurences of the value v_i
00048    *
00049    * The algorithm proceeds in 5 STEPS:
00050    *
00051    * STEP 1:
00052    *    Build the bipartite value-graph G=(<X,D>,E),
00053    *    with X = all variable nodes (each variable forms a node)
00054    *         D = all value nodes (union over all domains of the variables)
00055    *    and (x_i,v) is an edge in G iff value v is in the domain D_i of x_i
00056    *
00057    * STEP 2:   Compute a matching in the value graph.
00058    * STEP 3:   Compute all even alternating paths from unmatched  nodes
00059    * STEP 4:   Compute strongly connected components in the merged graph
00060    * STEP 5:   Update the Domains according to the computed edges
00061    *
00062    */
00063 
00064   template <class View, class Card, bool isView>
00065   inline
00066   Dom<View, Card, isView>::Dom(Space& home, ViewArray<View>& x0,
00067                                ViewArray<Card>& k0, bool cf)
00068     : Propagator(home), x(x0),  y(home, x0),
00069       k(k0), vvg(NULL), card_fixed(cf){
00070     // y is used for bounds propagation since prop_bnd needs all variables
00071     // values within the domain bounds
00072     home.notice(*this,AP_DISPOSE);
00073     x.subscribe(home, *this, PC_INT_DOM);
00074     k.subscribe(home, *this, PC_INT_DOM);
00075   }
00076 
00077   template <class View, class Card, bool isView>
00078   forceinline
00079   Dom<View, Card, isView>::Dom(Space& home, bool share,
00080                                Dom<View, Card, isView>& p)
00081     : Propagator(home, share, p), vvg(NULL), card_fixed(p.card_fixed) {
00082     x.update(home, share, p.x);
00083     y.update(home, share, p.y);
00084     k.update(home, share, p.k);
00085   }
00086 
00087   template <class View, class Card, bool isView>
00088   size_t
00089   Dom<View, Card, isView>::dispose(Space& home) {
00090     home.ignore(*this,AP_DISPOSE);
00091     if (!home.failed()) {
00092       x.cancel(home,*this, PC_INT_DOM);
00093       k.cancel(home,*this, PC_INT_DOM);
00094     }
00095     delete vvg;
00096     (void) Propagator::dispose(home);
00097     return sizeof(*this);
00098   }
00099 
00100   template <class View, class Card, bool isView>
00101   size_t
00102   Dom<View, Card, isView>::allocated(void) const {
00103     return (vvg == NULL) ? 0 : vvg->allocated();
00104   }
00105 
00106   template <class View, class Card, bool isView>
00107   Actor*
00108   Dom<View, Card, isView>::copy(Space& home, bool share) {
00109     return new (home) Dom<View, Card, isView>(home, share, *this);
00110   }
00111 
00112   template <class View, class Card, bool isView>
00113   PropCost
00114   Dom<View, Card, isView>::cost(const Space&, const ModEventDelta&) const {
00115 
00116     unsigned int n = x.size();
00117     unsigned int d = x[n-1].size();
00118     for (int i = n; i--; )
00119       if (x[i].size() > d)
00120         d = x[i].size();
00121 
00122     if (d < 6)
00123       return PropCost::linear(PropCost::LO,x.size());
00124     else if ((6 <= d) && (d < n/2))
00125       return PropCost::linear(PropCost::HI,x.size());
00126     else if ((n/2 <= d) && (d < n*n))
00127       return PropCost::quadratic(PropCost::LO,x.size());
00128     else
00129       return PropCost::cubic(PropCost::LO,x.size());
00130   }
00131 
00133   template <class View, class Card, bool isView>
00134   ExecStatus
00135   Dom<View, Card, isView>::propagate(Space& home, const ModEventDelta&) {
00136 
00137     ExecStatus es = ES_NOFIX;
00138     bool card_mod = false;
00139 
00140     Region r(home);
00141     int* count = r.alloc<int>(k.size());
00142     for (int i = k.size(); i--; )
00143       count[i] = 0;
00144 
00145     bool all_assigned = true;
00146     // total number of assigned views
00147     int noa = 0;
00148     for (int i = y.size(); i--; ) {
00149       bool b = y[i].assigned();
00150       all_assigned &= b;
00151       if (b) {
00152         noa++;
00153         int idx = lookupValue(k, y[i].val());
00154         if (idx == -1) {
00155           return ES_FAILED;
00156         }
00157         count[idx]++;
00158         if (isView) {
00159           if (k[idx].max() == 0) {
00160             return ES_FAILED;
00161           }
00162         }
00163       }
00164     }
00165 
00166     if (all_assigned) {
00167       for (int i = k.size(); i--; ) {
00168         int ci = count[i];
00169         if (!(k[i].min() <= ci && ci <= k[i].max())) {
00170           return ES_FAILED;
00171         }
00172         // the solution contains ci occurences of value k[i].card();
00173         if (isView) {
00174           if (!k[i].assigned()) {
00175             ModEvent me = k[i].eq(home, ci);
00176             if (me_failed(me))
00177               return ES_FAILED;
00178             card_mod |= me_modified(me);
00179           }
00180           all_assigned &= k[i].assigned();
00181         }
00182       }
00183       if (all_assigned)
00184         return ES_SUBSUMED(*this,home);
00185     }
00186 
00187     // before propagation performs inferences on cardinality variables:
00188     if (isView) {
00189       if (noa > 0) {
00190         int n  = y.size();
00191         int ks = k.size();
00192 
00193         for (int i = ks; i--; ) {
00194           if (!k[i].assigned()) {
00195             int ub = n - (noa - count[i]);
00196             int lb = count[i];
00197             ModEvent melq = k[i].lq(home, ub);
00198             if (me_failed(melq))
00199               return ES_FAILED;
00200             card_mod |= me_modified(melq);
00201 
00202             ModEvent megq = k[i].gq(home, lb);
00203             if (me_failed(megq))
00204               return ES_FAILED;
00205             card_mod |= me_modified(megq);
00206           }
00207         }
00208       }
00209 
00210       GECODE_ES_CHECK((prop_card<View, Card, true>(home, y, k, card_mod)));
00211 
00212       int smin = 0;
00213       int smax = 0;
00214       if (!card_consistent<View, Card>(smin, smax, y, k)) {
00215         return ES_FAILED;
00216       }
00217     }
00218 
00219     if (x.size() < 2) {
00220       assert(x.size() >= 0);
00221       if (x.size() == 0) {
00222         for (int j = k.size(); j--; ) {
00223           if (k[j].min() > k[j].counter() || k[j].max() < k[j].counter()) {
00224             return ES_FAILED;
00225           }
00226         }
00227         return ES_SUBSUMED(*this,home);
00228       } else {
00229         if (x.size() == 1) {
00230           if (x[0].assigned()) {
00231             int v = x[0].val();
00232             int idx = lookupValue(k,v);
00233             if (idx == -1) {
00234               return ES_FAILED;
00235             }
00236             ModEvent me = k[idx].inc();
00237             if (me_failed(me))
00238               return ES_FAILED;
00239             card_mod |= me_modified(me);
00240             for (int j = k.size(); j--; )
00241               if (k[j].min() > k[j].counter() || k[j].max() < k[j].counter())
00242                 return ES_FAILED;
00243             return ES_SUBSUMED(*this,home);
00244           }
00245         }
00246       }
00247     }
00248 
00249     assert(x.size() > 0);
00250 
00251     bool mod = false;
00252     bool min_req_mod = false;
00253     int noe     = 0;
00254     int smin    = 0;
00255     int smax    = 0;
00256     assert(noe >= 0);
00257     for (int i = x.size(); i--; ) {
00258       noe +=x[i].size();
00259     }
00260 
00261     assert(noe > 0);
00262 
00263     for (int i = k.size(); i--; ) {
00264       int ci = k[i].counter();
00265       if (ci > k[i].max() ) {
00266         return ES_FAILED;
00267       } else {
00268         smax += (k[i].max() - ci);
00269         if (ci < k[i].min()) {
00270           smin += (k[i].min() - ci);
00271         }
00272       }
00273     }
00274 
00275     if (x.size() < smin) {
00276       return ES_FAILED;
00277     }
00278 
00279     if (smax < x.size()) {
00280       return ES_FAILED;
00281     }
00282 
00283 
00284     if (vvg == NULL) {
00285       assert(noe > 0);
00286       assert(smin >= 0);
00287       assert(smax >= 0);
00288       vvg = new VarValGraph<View, Card, isView> (x, y, k, noe, smin, smax);
00289       min_req_mod = vvg->min_require(home);
00290       if (vvg->failed()) {
00291         return ES_FAILED;
00292       }
00293 
00294       bool init_ubm = vvg->template maximum_matching<UBC>(home);
00295       if (!init_ubm) {
00296         return ES_FAILED;
00297       }
00298 
00299       if (!card_fixed) {
00300         bool init_lbm = vvg->template maximum_matching<LBC>(home);
00301         if (!init_lbm) {
00302           return ES_FAILED;
00303         }
00304       }
00305     } else {
00306       if (!vvg->sync(home))
00307         return ES_FAILED;
00308     }
00309 
00310     bool filter_ubc = false;
00311     bool filter_lbc = false;
00312 
00313     vvg->template free_alternating_paths<UBC>(home);
00314     vvg->template strongly_connected_components<UBC>(home);
00315 
00316     filter_ubc = vvg->template narrow<UBC>(home);
00317     if (vvg->failed()) {
00318       return ES_FAILED;
00319     }
00320     if (!card_fixed) {
00321       if (isView && !vvg->sync(home))
00322         return ES_FAILED;
00323 
00324       vvg->template free_alternating_paths<LBC>(home);
00325       vvg->template strongly_connected_components<LBC>(home);
00326 
00327       filter_lbc = vvg->template narrow<LBC>(home);
00328       if (vvg->failed())
00329         return ES_FAILED;
00330     }
00331 
00332     bool card_assigned = true;
00333     if (isView) {
00334       es = prop_card<View, Card, true>(home, y, k, card_mod);
00335       if (es == ES_FAILED) {
00336         return ES_FAILED;
00337       }
00338 
00339       for (int i = k.size(); i--; ) {
00340         card_assigned &= k[i].assigned();
00341       }
00342     }
00343 
00344     if (card_assigned) {
00345       if (x.size() < 2) {
00346         assert(x.size() >= 0);
00347         if (x.size() == 0) {
00348           for (int j = k.size(); j--; ) {
00349             if (k[j].min() > k[j].counter() ||
00350                 k[j].max() < k[j].counter()) {
00351               return ES_FAILED;
00352             }
00353           }
00354           return ES_SUBSUMED(*this,home);
00355         } else {
00356           if (x.size() == 1) {
00357             if (x[0].assigned()) {
00358               int v = x[0].val();
00359               int idx = lookupValue(k,v);
00360               if (idx == -1) {
00361                 return ES_FAILED;
00362               }
00363               ModEvent me = k[idx].inc();
00364               if (me_failed(me)) {
00365                 return ES_FAILED;
00366               }
00367               card_mod |= me_modified(me);
00368 
00369               for (int j = k.size(); j--; ) {
00370                 if (k[j].min() > k[j].counter() ||
00371                     k[j].max() < k[j].counter()) {
00372                   return ES_FAILED;
00373                 }
00374               }
00375               return ES_SUBSUMED(*this,home);
00376             }
00377           }
00378         }
00379       }
00380     }
00381 
00382     for (int i = k.size(); i--; ) {
00383       count[i] = 0;
00384     }
00385     all_assigned = true;
00386     // total number of assigned views
00387     for (int i = y.size(); i--; ) {
00388       bool b = y[i].assigned();
00389       all_assigned &= b;
00390       if (b) {
00391         int idx = lookupValue(k,y[i].val());
00392         if (idx == -1) {
00393           return ES_FAILED;
00394         }
00395         count[idx]++;
00396         if (isView) {
00397           if (k[idx].max() == 0) {
00398             return ES_FAILED;
00399           }
00400         }
00401       }
00402     }
00403 
00404     if (isView) {
00405       es = prop_card<View, Card, true>(home, y, k, card_mod);
00406       if (es == ES_FAILED) {
00407         return es;
00408       }
00409     }
00410 
00411     if (all_assigned) {
00412       for (int i = k.size(); i--; ) {
00413         int ci = count[i];
00414         if (!(k[i].min() <= ci && ci <= k[i].max())) {
00415           return ES_FAILED;
00416         }
00417         // the solution contains ci occurences of value k[i].card();
00418         if (isView) {
00419           if (!k[i].assigned()) {
00420             ModEvent me = k[i].eq(home, ci);
00421             if (me_failed(me))
00422               return ES_FAILED;
00423             card_mod |= me_modified(me);
00424           }
00425           all_assigned &= k[i].assigned();
00426         }
00427       }
00428       if (all_assigned) {
00429         return ES_SUBSUMED(*this,home);
00430       }
00431     }
00432 
00433     if (isView) {
00434       int smax = 0;
00435       int smin = 0;
00436       for (int i = k.size(); i--; ) {
00437         smax += k[i].max();
00438       }
00439       int ysmax = y.size() - smax;
00440       int ysmin = y.size() - smin;
00441       smax = 0;
00442       smin = 0;
00443       bool card_ass = true;
00444       for (int i = k.size(); i--; ) {
00445         int lb = ysmax + k[i].max();
00446         int ub = ysmin + k[i].min();
00447         ModEvent me = k[i].gq(home, lb);
00448         if (me_failed(me))
00449           return ES_FAILED;
00450 
00451         card_mod |= me_modified(me);
00452         smax += k[i].max();
00453 
00454         me = k[i].lq(home, ub);
00455         if (me_failed(me))
00456           return ES_FAILED;
00457 
00458         card_mod |= me_modified(me);
00459         card_ass &= k[i].assigned();
00460       }
00461       if (card_ass) {
00462         if (smax < y.size() || smax > y.size()) {
00463           return ES_FAILED;
00464         }
00465       }
00466     }
00467 
00468     mod = (filter_ubc || filter_lbc || min_req_mod || card_mod);
00469 
00470     return mod ? ES_NOFIX : ES_FIX;
00471 
00472   }
00473 
00474   template <class View, class Card, bool isView>
00475   inline ExecStatus
00476   Dom<View, Card, isView>::post(Space& home, ViewArray<View>& x0,
00477                                 ViewArray<Card>& k0){
00478     bool cardfix = true;
00479     for (int i = k0.size(); i--; ) {
00480       cardfix &= k0[i].assigned();
00481     }
00482 
00483     (void) new (home) Dom<View, Card, isView>(home, x0, k0, cardfix);
00484     return ES_OK;
00485   }
00486 
00487 }}}
00488 
00489 
00490 
00491 // STATISTICS: int-prop
00492