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  *     Christian Schulte <schulte@gecode.org>
00004  *
00005  *  Copyright:
00006  *     Christian Schulte, 2003
00007  *
00008  *  Last modified:
00009  *     $Date: 2006-10-23 16:16:09 +0200 (Mon, 23 Oct 2006) $ by $Author: schulte $
00010  *     $Revision: 3768 $
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 <climits>
00023 
00024 #include "gecode/support/dynamic-array.hh"
00025 #include "gecode/support/static-stack.hh"
00026 
00027 #include "gecode/iter.hh"
00028 
00029 namespace Gecode { namespace Int { namespace Distinct {
00030 
00038   template <class T>
00039   class CombPtrFlag {
00040   private:
00042     ptrdiff_t cpf;
00043   public:
00045     CombPtrFlag(T* p1, T* p2);
00047     void init(T* p1, T* p2);
00049     T* ptr(T* p) const;
00051     int is_set(void) const;
00053     void set(void);
00055     void unset(void);
00056   };
00057 
00062   class BiLink {
00063   private:
00064     BiLink* _prev; BiLink* _next;
00065   public:
00066     BiLink(void);
00067 
00068     BiLink* prev(void) const; void prev(BiLink*);
00069     BiLink* next(void) const; void next(BiLink*);
00070 
00071     void add(BiLink*);
00072     void unlink(void);
00073 
00074     void mark(void);
00075     bool marked(void) const;
00076 
00077     bool empty(void) const;
00078   };
00079 
00080   template <class View> class Edge;
00081 
00091   template <class View>
00092   class Node : public BiLink {
00093   public:
00094     unsigned int pre, low, comp;
00095 
00096     Node(void);
00097 
00098     Edge<View>* edge_fst(void) const;
00099     Edge<View>* edge_lst(void) const;
00100 
00101     static void* operator new(size_t, void*);
00102   };
00103 
00108   template <class View>
00109   class ValNode : public Node<View> {
00110   protected:
00111     const int _val; Edge<View>* _matching;
00112   public:
00113     ValNode(int);
00114     int val(void) const;
00115     void matching(Edge<View>*);
00116     Edge<View>* matching(void) const;
00117   };
00118 
00123   template <class View>
00124   class ViewNode : public Node<View> {
00125   protected:
00126     Edge<View>* _val_edges; View _view;
00127   public:
00128     ViewNode(View);
00129     Edge<View>*  val_edges(void) const;
00130     Edge<View>** val_edges_ref(void);
00131 
00132     View view(void) const;
00133   };
00134 
00139   template <class View>
00140   class Edge : public BiLink {
00141   protected:
00142     Edge<View>*              _next_edge;
00143     CombPtrFlag<Node<View> > sd;
00144   public:
00145     Edge(Node<View>*, Node<View>*);
00146 
00147     Node<View>* dst(Node<View>*) const;
00148 
00149     ViewNode<View>* view(ValNode<View>*) const;
00150     ValNode<View>* val(ViewNode<View>*) const;
00151 
00152     bool used(Node<View>*) const;
00153     void use(void);
00154     void free(void);
00155 
00156     void revert(Node<View>*);
00157 
00158     Edge<View>*  next_edge(void) const;
00159     Edge<View>** next_edge_ref(void);
00160 
00161     Edge<View>* next(void) const;
00162     static void* operator new(size_t, void*);
00163   };
00164 
00165 }}}
00166 
00167 #include "gecode/int/distinct/combptr.icc"
00168 #include "gecode/int/distinct/bilink.icc"
00169 #include "gecode/int/distinct/node.icc"
00170 #include "gecode/int/distinct/edge.icc"
00171 
00172 namespace Gecode { namespace Int { namespace Distinct {
00173 
00178   template <class View>
00179   class DomCtrl<View>::ViewValGraph {
00180   protected:
00181     ViewNode<View>** view; int n_view;
00182     ValNode<View>** val; int n_val;
00183     char* mem;
00184     unsigned int count;
00185     unsigned int cnt0;
00186     unsigned int cnt1;
00187     Support::StaticStack<Node<View>*> n_s;
00188   public:
00189     ViewValGraph(int, View*, const int*, int, unsigned int);
00190     ViewValGraph(int, View*, int, unsigned int, int);
00191     ~ViewValGraph(void);
00192 
00193     size_t size;
00194 
00195     static ViewValGraph* init(int,View*);
00196 
00197     bool initial_match(void);
00198 
00199     void mark(void);
00200     void tell(Space*);
00201 
00202     bool overflow(void) const;
00203 
00204     bool sync(void);
00205 
00206   protected:
00207     bool search_match(ViewNode<View>*);
00208     bool match(ViewNode<View>*);
00209     void scc(Node<View>*);
00210 
00211   public:
00212     // Memory management
00213     static void* operator new(size_t);
00214     static void  operator delete(void*);
00215   };
00216 
00217 
00218   template <class View>
00219   forceinline
00220   DomCtrl<View>::ViewValGraph::ViewValGraph(int n_view0, View* x,
00221                                             int n_val0,
00222                                             unsigned int n_edges, int min)
00223     :  n_view(n_view0), n_val(n_val0),
00224        count(0), cnt0(0), cnt1(0), n_s(n_view+n_val)
00225   {
00226     size_t edge_size  = sizeof(Edge<View>) * n_edges;
00227     size_t views_size = sizeof(ViewNode<View>) * n_view;
00228     size_t view_size  = sizeof(ViewNode<View>*) * n_view;
00229     size_t vals_size  = sizeof(ValNode<View>) * n_val;
00230     size_t val_size   = sizeof(ValNode<View>*) * n_val;
00231     size_t size = edge_size +
00232       views_size + view_size + vals_size + val_size;
00233     mem = reinterpret_cast<char*>(Memory::malloc(size));
00234     Edge<View>*     edges      = reinterpret_cast<Edge<View>*>(mem);
00235     ViewNode<View>* view_nodes = reinterpret_cast<ViewNode<View>*>
00236       (mem+edge_size);
00237     ValNode<View>*  val_nodes  = reinterpret_cast<ValNode<View>*>
00238       (mem+edge_size+views_size);
00239     view = reinterpret_cast<ViewNode<View>**>
00240       (mem+edge_size+views_size+vals_size);
00241     val  = reinterpret_cast<ValNode<View>**>
00242       (mem+edge_size+views_size+vals_size+view_size);
00243 
00244     // Init value nodes
00245     {
00246       int v = min+n_val;
00247       for (int i = n_val; i--; )
00248         val[i] = new (val_nodes + i) ValNode<View>(--v);
00249     }
00250 
00251     // Init view nodes and edges
00252     for (int i = n_view; i--; ) {
00253       view[i] = new (view_nodes + i) ViewNode<View>(x[i]);
00254       Edge<View>** edge_p = view[i]->val_edges_ref();
00255       ViewValues<View> x_i(x[i]);
00256       while (x_i()) {
00257         *edge_p = new (edges++) Edge<View>(val_nodes+x_i.val()-min,
00258                                            view_nodes+i);
00259         edge_p = (*edge_p)->next_edge_ref();
00260         ++x_i;
00261       }
00262       *edge_p = NULL;
00263     }
00264   }
00265 
00266   template <class View>
00267   forceinline
00268   DomCtrl<View>::ViewValGraph::ViewValGraph(int n_view0, View* x,
00269                                             const int* val_inf,
00270                                             int n_val0, unsigned int n_edges)
00271     :  n_view(n_view0), n_val(n_val0),
00272        count(0), cnt0(0), cnt1(0), n_s(n_view+n_val)
00273   {
00274     size_t edge_size  = sizeof(Edge<View>) * n_edges;
00275     size_t views_size = sizeof(ViewNode<View>) * n_view;
00276     size_t view_size  = sizeof(ViewNode<View>*) * n_view;
00277     size_t vals_size  = sizeof(ValNode<View>) * n_val;
00278     size_t val_size   = sizeof(ValNode<View>*) * n_val;
00279     size_t size = edge_size +
00280       views_size + view_size + vals_size + val_size;
00281     mem = reinterpret_cast<char*>(Memory::malloc(size));
00282     Edge<View>*     edges      = reinterpret_cast<Edge<View>*>(mem);
00283     ViewNode<View>* view_nodes = reinterpret_cast<ViewNode<View>*>
00284       (mem+edge_size);
00285     ValNode<View>*  val_nodes  = reinterpret_cast<ValNode<View>*>
00286       (mem+edge_size+views_size);
00287     view = reinterpret_cast<ViewNode<View>**>
00288       (mem+edge_size+views_size+vals_size);
00289     val  = reinterpret_cast<ValNode<View>**>
00290       (mem+edge_size+views_size+vals_size+view_size);
00291 
00292     // Init value nodes
00293     for (int i = n_val; i--; )
00294       val[i] = new (val_nodes + i) ValNode<View>(val_inf[i]);
00295 
00296     // Init view nodes
00297     for (int i = n_view; i--; ) {
00298       view[i] = new (view_nodes + i) ViewNode<View>(x[i]);
00299       Edge<View>** edge_p = view[i]->val_edges_ref();
00300       ViewValues<View> x_i(x[i]);
00301       int j = 0;
00302       while (x_i()) {
00303         while (val_inf[j] < x_i.val())
00304           j++;
00305         *edge_p = new (edges++) Edge<View>(val_nodes+j,view_nodes+i);
00306         edge_p = (*edge_p)->next_edge_ref();
00307         ++x_i;
00308       }
00309       *edge_p = NULL;
00310     }
00311   }
00312 
00313   template <class View>
00314   typename DomCtrl<View>::ViewValGraph*
00315   DomCtrl<View>::ViewValGraph::init(int n_view, View* x) {
00316     // Find value information for construction of view value graph
00317     int min = x[n_view-1].min();
00318     int max = x[n_view-1].max();
00319     unsigned int size = x[n_view-1].size();
00320     for (int i=n_view-1; i--; ) {
00321       size += x[i].size();
00322       min = std::min(min,x[i].min());
00323       max = std::max(max,x[i].max());
00324     }
00325 
00326     unsigned int width = max-min+1;
00327 
00328     // Definitly not enough values
00329     if (width < static_cast<unsigned int>(n_view))
00330       return NULL;
00331 
00332     // Test whether the values are dense or sparse
00333     if (static_cast<unsigned int>(n_view)*2 >= width)
00334       return new ViewValGraph(n_view,x,static_cast<int>(width),size,min);
00335 
00336     Support::DynamicArray<int> val_inf(64);
00337     // Compute set of values
00338     int n_val = 0;
00339     GECODE_AUTOARRAY(ViewRanges<View>,x_r,n_view);
00340     for (int i = n_view; i--; )
00341       x_r[i].init(x[i]);
00342     Iter::Ranges::NaryUnion<ViewRanges<View> > xu(x_r, n_view);
00343     // Of course, the union of non-empty iterators is non-empty
00344     assert(xu());
00345     // Fill array of values
00346     do {
00347       for (int v = xu.min(); v <= xu.max(); v++)
00348         val_inf[n_val++] = v;
00349       ++xu;
00350     } while (xu());
00351     if (n_val < n_view)
00352       return NULL;
00353     return new ViewValGraph(n_view,x,val_inf,n_val,size);
00354   }
00355 
00356   template <class View>
00357   bool
00358   DomCtrl<View>::ViewValGraph::search_match(ViewNode<View>* x) {
00359     x->comp = count;
00360     // Try to find matching edge cheaply: is there a free edge around?
00361     {
00362       Edge<View>* e = x->val_edges();
00363       // This holds true as domains are never empty
00364       assert(e != NULL);
00365       do {
00366         if (!e->val(x)->matching()) {
00367           e->revert(x); e->val(x)->matching(e);
00368           return true;
00369         }
00370         e = e->next_edge();
00371       } while (e != NULL);
00372     }
00373     // No, find matching edge by augmenting path method
00374     {
00375       Edge<View>* e = x->val_edges();
00376       do {
00377         ValNode<View>*  n = e->val(x);
00378         ViewNode<View>* y = n->matching()->view(n);
00379         if ((y->comp < count) && search_match(y)) {
00380           n->matching()->revert(n);
00381           e->revert(x); n->matching(e);
00382           return true;
00383         }
00384         e = e->next_edge();
00385       } while (e != NULL);
00386     }
00387     return false;
00388   }
00389 
00390   template <class View>
00391   forceinline bool
00392   DomCtrl<View>::ViewValGraph::match(ViewNode<View>* x) {
00393     assert(x->edge_fst() == x->edge_lst());
00394     count++;
00395     return search_match(x);
00396   }
00397 
00398   template <class View>
00399   bool
00400   DomCtrl<View>::ViewValGraph::initial_match(void) {
00401     for (int i = n_view; i--; )
00402       if (!match(view[i]))
00403         return false;
00404     return true;
00405   }
00406 
00407   template <class View>
00408   void
00409   DomCtrl<View>::ViewValGraph::scc(Node<View>* w) {
00410     w->pre = cnt0;
00411     w->low = cnt0;
00412     unsigned int min = cnt0++;
00413     n_s.push(w);
00414     for (Edge<View>* e = w->edge_fst(); e != w->edge_lst(); e = e->next()) {
00415       Node<View>* v = e->dst(w);
00416       if (v->pre < count)
00417         scc(v);
00418       if (v->low < min)
00419         min = v->low;
00420     }
00421     if (min < w->low) {
00422       w->low = min;
00423       return;
00424     }
00425     do {
00426       Node<View>* v = n_s.pop();
00427       v->comp = cnt1;
00428       v->low  = UINT_MAX;
00429     } while (n_s.last() != w);
00430     cnt1++;
00431   }
00432 
00433   template <class View>
00434   forceinline void
00435   DomCtrl<View>::ViewValGraph::mark(void) {
00436     // Marks all edges as used that are on simple paths in the graph
00437     // that start from a free (unmatched node) by depth-first-search
00438     n_s.reset();
00439     // Insert all free nodes: they can be only value nodes as we
00440     // have a maximum matching covering all view nodes
00441     count++;
00442     for (int i = n_val; i--; )
00443       if (!val[i]->matching())
00444         // Is it orphaned?
00445         if (val[i]->empty()) {
00446           val[i] = val[--n_val];
00447         } else {
00448           val[i]->comp = count;
00449           n_s.push(val[i]);
00450         }
00451 
00452     // Invariant: only value nodes are on the stack!
00453     while (!n_s.empty()) {
00454       ValNode<View>* n = static_cast<ValNode<View>*>(n_s.pop());
00455       for (Edge<View>* e = n->edge_fst(); e != n->edge_lst(); e = e->next()) {
00456         // Get the value node
00457         e->use();
00458         ViewNode<View>* x = e->view(n);
00459         if (x->comp < count) {
00460           x->comp = count;
00461           assert(x->edge_fst()->next() == x->edge_lst());
00462           ValNode<View>* m = x->edge_fst()->val(x);
00463           x->edge_fst()->use();
00464           if (m->comp < count) {
00465             m->comp = count;
00466             n_s.push(m);
00467           }
00468         }
00469       }
00470     }
00471 
00472     count++;
00473     cnt0 = count;
00474     cnt1 = count;
00475     n_s.reset();
00476     for (int i = n_view; i--; )
00477       if (view[i]->comp < count)
00478         scc(view[i]);
00479     count = cnt0+1;
00480   }
00481 
00482   template <class View>
00483   forceinline void
00484   DomCtrl<View>::ViewValGraph::tell(Space* home) {
00485     // Tell constraints and also eliminate nodes and edges
00486     for (int i = n_view; i--; )
00487       if (!view[i]->edge_fst()->used(view[i])) {
00488         view[i]->view().eq(home,view[i]->edge_fst()->val(view[i])->val());
00489         view[i]->edge_fst()->val(view[i])->matching(NULL);
00490         view[i] = view[--n_view];
00491       } else {
00492         for (Edge<View>* e = view[i]->val_edges(); e!=NULL; e = e->next_edge())
00493           if (!e->used(view[i])) {
00494             view[i]->view().nq(home,e->val(view[i])->val());
00495           }
00496       }
00497   }
00498 
00499   template <class View>
00500   forceinline bool
00501   DomCtrl<View>::ViewValGraph::overflow(void) const {
00502     return count > (UINT_MAX >> 1);
00503   }
00504 
00505   template <class View>
00506   bool
00507   DomCtrl<View>::ViewValGraph::sync(void) {
00508     // Stack for view nodes to be rematched
00509     GECODE_AUTOARRAY(ViewNode<View>*,re,n_view);
00510     int n_re = 0;
00511     // Synchronize nodes
00512     for (int i = n_view; i--; ) {
00513       ViewNode<View>* x = view[i];
00514       if (x->view().assigned()) {
00515         x->edge_fst()->val(x)->matching(NULL);
00516         for (Edge<View>* e = x->val_edges(); e != NULL; e = e->next_edge())
00517           e->unlink();
00518         view[i] = view[--n_view];
00519       } else {
00520         ViewRanges<View> r(x->view());
00521         Edge<View>*  m = x->edge_fst();      // Matching edge
00522         Edge<View>** p = x->val_edges_ref();
00523         Edge<View>*  e = *p;
00524         do {
00525           while (e->val(x)->val() < r.min()) {
00526             // Skip edge
00527             e->unlink(); e->mark();
00528             e = e->next_edge();
00529             *p = e;
00530           }
00531           assert(r.min() == e->val(x)->val());
00532           // This edges must be kept
00533           for (unsigned int i=r.width(); i--; ) {
00534             e->free();
00535             p = e->next_edge_ref();
00536             e = e->next_edge();
00537           }
00538           ++r;
00539         } while (r());
00540         *p = NULL;
00541         while (e != NULL) {
00542           e->unlink(); e->mark();
00543           e = e->next_edge();
00544         }
00545         if (m->marked()) {
00546           // Matching has been deleted!
00547           m->val(x)->matching(NULL);
00548           re[n_re++] = x;
00549         }
00550       }
00551     }
00552     while (n_re--)
00553       if (!match(re[n_re]))
00554         return false;
00555     return true;
00556   }
00557 
00558   template <class View>
00559   forceinline
00560   DomCtrl<View>::ViewValGraph::~ViewValGraph(void) {
00561     Memory::free(mem);
00562   }
00563 
00564   template <class View>
00565   forceinline void*
00566   DomCtrl<View>::ViewValGraph::operator new(size_t s) {
00567     return Memory::malloc(s);
00568   }
00569   template <class View>
00570   forceinline void
00571   DomCtrl<View>::ViewValGraph::operator delete(void* p) {
00572     Memory::free(p);
00573   }
00574 
00575   /*
00576    * The propagation controller
00577    *
00578    */
00579 
00580   template <class View>
00581   forceinline
00582   DomCtrl<View>::DomCtrl(void) : vvg(NULL) {}
00583 
00584   template <class View>
00585   forceinline bool
00586   DomCtrl<View>::available(void) {
00587     if ((vvg != NULL) && vvg->overflow()) {
00588       delete vvg;
00589       vvg = NULL;
00590     }
00591     return vvg != NULL;
00592   }
00593 
00594   template <class View>
00595   forceinline ExecStatus
00596   DomCtrl<View>::init(int n, View* x) {
00597     assert(vvg == NULL);
00598     vvg = ViewValGraph::init(n,x);
00599     if ((vvg == NULL) || !vvg->initial_match())
00600       return ES_FAILED;
00601     return ES_OK;
00602   }
00603 
00604   template <class View>
00605   forceinline ExecStatus
00606   DomCtrl<View>::sync(void) {
00607     return vvg->sync() ? ES_OK : ES_FAILED;
00608   }
00609 
00610   template <class View>
00611   forceinline void
00612   DomCtrl<View>::propagate(Space* home) {
00613     vvg->mark();
00614     vvg->tell(home);
00615   }
00616 
00617   template <class View>
00618   forceinline void
00619   DomCtrl<View>::flush(void) {
00620     delete vvg; vvg = NULL;
00621   }
00622 
00623   template <class View>
00624   forceinline size_t
00625   DomCtrl<View>::size(void) const {
00626     return (vvg != NULL) ? vvg->size : 0;
00627   }
00628 
00629   template <class View>
00630   forceinline void
00631   DomCtrl<View>::dispose(void) {
00632     delete vvg;
00633   }
00634 
00635 
00636 
00637   /*
00638    * The propagator proper
00639    *
00640    */
00641 
00642   template <class View>
00643   forceinline
00644   Dom<View>::Dom(Space* home, ViewArray<View>& x)
00645     : NaryPropagator<View,PC_INT_DOM>(home,x,true) {}
00646 
00647   template <class View>
00648   ExecStatus
00649   Dom<View>::post(Space* home, ViewArray<View>& x) {
00650     if (x.size() == 2)
00651       return Rel::Nq<View>::post(home,x[0],x[1]);
00652     if (x.size() == 3)
00653       return TerDom<View>::post(home,x[0],x[1],x[2]);
00654     if (x.size() > 3) {
00655       // Do bounds propagation to make view-value graph smaller
00656       if (prop_bnd<View>(home,x,x.size()) == ES_FAILED)
00657         return ES_FAILED;
00658       (void) new (home) Dom<View>(home,x);
00659     }
00660     return ES_OK;
00661   }
00662 
00663   template <class View>
00664   forceinline
00665   Dom<View>::Dom(Space* home, bool share, Dom<View>& p)
00666     : NaryPropagator<View,PC_INT_DOM>(home,share,p) {}
00667 
00668   template <class View>
00669   void
00670   Dom<View>::flush(void) {
00671     dc.flush();
00672   }
00673 
00674   template <class View>
00675   size_t
00676   Dom<View>::size(void) const {
00677     return dc.size();
00678   }
00679 
00680   template <class View>
00681   PropCost
00682   Dom<View>::cost(void) const {
00683     return cost_lo(x.size(),
00684                    (View::pme(this) == ME_INT_VAL)
00685                    ? PC_LINEAR_LO : PC_CUBIC_LO);
00686   }
00687 
00688   template <class View>
00689   Actor*
00690   Dom<View>::copy(Space* home, bool share) {
00691     return new (home) Dom<View>(home,share,*this);
00692   }
00693 
00694   template <class View>
00695   ExecStatus
00696   Dom<View>::propagate(Space* home) {
00697     if (View::pme(this) == ME_INT_VAL) {
00698       ExecStatus es = prop_val<View,false>(home,x);
00699       if ((es == ES_FAILED) || (es == ES_SUBSUMED))
00700         return es;
00701       if (es == ES_FIX)
00702         return this->ES_FIX_PARTIAL(View::pme(ME_INT_DOM));
00703       if (prop_bnd<View>(home,x,x.size()) == ES_FAILED)
00704         return ES_FAILED;
00705       es = prop_val<View,true>(home,x);
00706       if ((es == ES_FAILED) || (es == ES_SUBSUMED))
00707         return es;
00708       return this->ES_FIX_PARTIAL(View::pme(ME_INT_DOM));
00709     }
00710 
00711     if (x.size() == 2) {
00712       GECODE_ES_CHECK(Rel::Nq<View>::post(home,x[0],x[1]));
00713       return ES_SUBSUMED;
00714     }
00715     if (x.size() == 3) {
00716       GECODE_ES_CHECK(TerDom<View>::post(home,x[0],x[1],x[2]));
00717       return ES_SUBSUMED;
00718     }
00719 
00720     if (dc.available()) {
00721       GECODE_ES_CHECK(dc.sync());
00722     } else {
00723       GECODE_ES_CHECK(dc.init(x.size(),&x[0]));
00724     }
00725     dc.propagate(home);
00726     return ES_FIX;
00727   }
00728 
00729   template <class View>
00730   size_t
00731   Dom<View>::dispose(Space* home) {
00732     dc.dispose();
00733     (void) NaryPropagator<View,PC_INT_DOM>::dispose(home);
00734     return sizeof(*this);
00735   }
00736 
00737 }}}
00738 
00739 // STATISTICS: int-prop
00740