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

dom.icc

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