Generated on Mon Aug 25 11:35:36 2008 for Gecode by doxygen 1.5.6

dom.icc

Go to the documentation of this file.
00001 /* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
00002 /*
00003  *  Main authors:
00004  *     Christian Schulte <schulte@gecode.org>
00005  *
00006  *  Copyright:
00007  *     Christian Schulte, 2003
00008  *
00009  *  Last modified:
00010  *     $Date: 2008-07-11 11:14:16 +0200 (Fri, 11 Jul 2008) $ by $Author: tack $
00011  *     $Revision: 7359 $
00012  *
00013  *  This file is part of Gecode, the generic constraint
00014  *  development environment:
00015  *     http://www.gecode.org
00016  *
00017  *  Permission is hereby granted, free of charge, to any person obtaining
00018  *  a copy of this software and associated documentation files (the
00019  *  "Software"), to deal in the Software without restriction, including
00020  *  without limitation the rights to use, copy, modify, merge, publish,
00021  *  distribute, sublicense, and/or sell copies of the Software, and to
00022  *  permit persons to whom the Software is furnished to do so, subject to
00023  *  the following conditions:
00024  *
00025  *  The above copyright notice and this permission notice shall be
00026  *  included in all copies or substantial portions of the Software.
00027  *
00028  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00029  *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00030  *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00031  *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
00032  *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
00033  *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
00034  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00035  *
00036  */
00037 
00038 #include <climits>
00039 
00040 namespace Gecode { namespace Int { namespace Distinct {
00041 
00049   template <class T>
00050   class CombPtrFlag {
00051   private:
00053     ptrdiff_t cpf;
00054   public:
00056     CombPtrFlag(T* p1, T* p2);
00058     void init(T* p1, T* p2);
00060     T* ptr(T* p) const;
00062     int is_set(void) const;
00064     void set(void);
00066     void unset(void);
00067   };
00068 
00073   class BiLink {
00074   private:
00075     BiLink* _prev; BiLink* _next;
00076   public:
00077     BiLink(void);
00078 
00079     BiLink* prev(void) const; void prev(BiLink*);
00080     BiLink* next(void) const; void next(BiLink*);
00081 
00082     void add(BiLink*);
00083     void unlink(void);
00084 
00085     void mark(void);
00086     bool marked(void) const;
00087 
00088     bool empty(void) const;
00089   };
00090 
00091   template <class View> class Edge;
00092 
00102   template <class View>
00103   class Node : public BiLink {
00104   public:
00105     unsigned int low, min, comp;
00106     Edge<View>* iter;
00107 
00108     Node(void);
00109 
00110     Edge<View>* edge_fst(void) const;
00111     Edge<View>* edge_lst(void) const;
00112 
00113     static void  operator delete(void*, size_t);
00114     static void  operator delete(void*,Space*);
00115     static void* operator new(size_t, Space*);
00116   };
00117 
00122   template <class View>
00123   class ValNode : public Node<View> {
00124   protected:
00126     const int      _val; 
00128     Edge<View>*    _matching;
00130     ValNode<View>* _next_val;
00131   public:
00133     ValNode(int v);
00135     ValNode(int v, ValNode<View>* n);
00137     int val(void) const;
00139     void matching(Edge<View>* m);
00141     Edge<View>* matching(void) const;
00143     ValNode<View>** next_val_ref(void);
00145     ValNode<View>* next_val(void) const;
00147     void next_val(ValNode<View>* v);
00148   };
00149 
00154   template <class View>
00155   class ViewNode : public Node<View> {
00156   protected:
00158     View        _view;    
00160     Edge<View>* _val_edges; 
00161   public:
00163     ViewNode(View x);
00165     Edge<View>*  val_edges(void) const;
00167     Edge<View>** val_edges_ref(void);
00169     View view(void) const;
00170   };
00171 
00176   template <class View>
00177   class Edge : public BiLink {
00178   protected:
00180     Edge<View>*              _next_edge;
00182     CombPtrFlag<Node<View> > sd;
00183   public:
00185     Edge(ValNode<View>* v, ViewNode<View>* x);
00187     Node<View>* dst(Node<View>* s) const;
00188 
00190     ViewNode<View>* view(ValNode<View>* v) const;
00192     ValNode<View>* val(ViewNode<View>* x) const;
00193 
00194     bool used(Node<View>*) const;
00195     void use(void);
00196     void free(void);
00197 
00198     void revert(Node<View>*);
00199 
00200     Edge<View>*  next_edge(void) const;
00201     Edge<View>** next_edge_ref(void);
00202 
00203     Edge<View>* next(void) const;
00204 
00205     static void  operator delete(void*, size_t);
00206     static void  operator delete(void*,Space*);
00207     static void* operator new(size_t, Space*);
00208   };
00209 
00210 }}}
00211 
00212 #include "gecode/int/distinct/combptr.icc"
00213 #include "gecode/int/distinct/bilink.icc"
00214 #include "gecode/int/distinct/edge.icc"
00215 #include "gecode/int/distinct/node.icc"
00216 
00217 namespace Gecode { namespace Int { namespace Distinct {
00218 
00219 
00220   template <class View>
00221   forceinline
00222   DomCtrl<View>::ViewValGraph::ViewValGraph(void)
00223     : view(NULL), val(NULL), count(1) {}
00224 
00225   template <class View>
00226   forceinline bool
00227   DomCtrl<View>::ViewValGraph::initialized(void) const {
00228     return view != NULL;
00229   }
00230 
00231   template <class View>
00232   forceinline bool
00233   DomCtrl<View>::ViewValGraph::match(MatchStack& m, ViewNode<View>* x) {
00234     count++;
00235   start:
00236     // Try to find matching edge cheaply: is there a free edge around?
00237     {
00238       Edge<View>* e = x->val_edges();
00239       // This holds true as domains are never empty
00240       assert(e != NULL);
00241       do {
00242         if (!e->val(x)->matching()) {
00243           e->revert(x); e->val(x)->matching(e);
00244           // Found a matching, revert all edges on stack
00245           while (!m.empty()) {
00246             x = m.pop(); e = x->iter;
00247             e->val(x)->matching()->revert(e->val(x));
00248             e->revert(x); e->val(x)->matching(e);
00249           }
00250           return true;
00251         }
00252         e = e->next_edge();
00253       } while (e != NULL);
00254     }
00255     // No, find matching edge by augmenting path method
00256     Edge<View>* e = x->val_edges();
00257     do {
00258       if (e->val(x)->matching()->view(e->val(x))->min < count) { 
00259         e->val(x)->matching()->view(e->val(x))->min = count;
00260         m.push(x); x->iter = e;
00261         x = e->val(x)->matching()->view(e->val(x));
00262         goto start;
00263       }
00264     next:
00265       e = e->next_edge();
00266     } while (e != NULL);
00267     if (!m.empty()) {
00268       x = m.pop(); e = x->iter; goto next;
00269     }
00270     // All nodes and edges unsuccessfully tried
00271     return false;
00272   }
00273 
00274   template <class View>
00275   ExecStatus
00276   DomCtrl<View>::ViewValGraph::init(Space* home, int n, View* x) {
00277     n_view = n; 
00278     view = static_cast<ViewNode<View>**>
00279       (home->alloc(n_view*sizeof(ViewNode<View>*)));
00280 
00281     // Find value information for construction of view value graph
00282     int min = x[n_view-1].min();
00283     int max = x[n_view-1].max();
00284     for (int i=n_view-1; i--; ) {
00285       min = std::min(min,x[i].min());
00286       max = std::max(max,x[i].max());
00287     }
00288 
00289     unsigned int width = max-min+1;
00290 
00291     // Definitly not enough values
00292     if (width < static_cast<unsigned int>(n_view))
00293       return ES_FAILED;
00294 
00295     n_val = 0;
00296     val = NULL;
00297 
00298     if (static_cast<unsigned int>(n_view)*4 >= width) {
00299       // Values are dense: use a mapping
00300       GECODE_AUTOARRAY(ValNode<View>*,val2node,width);
00301 
00302       for (unsigned int i=width; i--; )
00303         val2node[i]=NULL;
00304 
00305       for (int i=n; i--; ) {
00306         view[i] = new (home) ViewNode<View>(x[i]);
00307         Edge<View>** edge_p = view[i]->val_edges_ref();
00308         ViewValues<View> xi(x[i]);
00309         while (xi()) {
00310           if (val2node[xi.val()-min] == NULL)
00311             val2node[xi.val()-min] = new (home) ValNode<View>(xi.val());
00312           *edge_p = new (home) Edge<View>(val2node[xi.val()-min],view[i]);
00313           edge_p = (*edge_p)->next_edge_ref();
00314           ++xi;
00315         }
00316         *edge_p = NULL;
00317       }
00318 
00319       for (unsigned int i=width; i--; )
00320         if (val2node[i] != NULL) {
00321           val2node[i]->next_val(val);
00322           val = val2node[i];
00323           n_val++;
00324         }
00325 
00326     } else {
00327       // Values are sparse
00328       for (int i=n; i--; ) {
00329         view[i] = new (home) ViewNode<View>(x[i]);
00330         Edge<View>** edge_p = view[i]->val_edges_ref();
00331         ViewValues<View> xi(x[i]);
00332         ValNode<View>** v = &val;
00333         while (xi() && (*v != NULL)) {
00334           if ((*v)->val() == xi.val()) {
00335             // Value node does already exist, create new edge
00336             *edge_p = new (home) Edge<View>(*v,view[i]);
00337             edge_p = (*edge_p)->next_edge_ref();
00338             v = (*v)->next_val_ref();
00339             ++xi;
00340           } else if ((*v)->val() < xi.val()) {
00341             // Skip to next value node
00342             v = (*v)->next_val_ref();
00343           } else {
00344             // Value node does not yet exist, create and link it
00345             ValNode<View>* nv = new (home) ValNode<View>(xi.val(),*v);
00346             *v = nv; v = nv->next_val_ref();
00347             *edge_p = new (home) Edge<View>(nv,view[i]);
00348             edge_p = (*edge_p)->next_edge_ref();
00349             ++xi; n_val++;
00350           }
00351         }
00352         // Create missing value nodes
00353         while (xi()) {
00354           ValNode<View>* nv = new (home) ValNode<View>(xi.val(),*v);
00355           *v = nv; v = nv->next_val_ref();
00356           *edge_p = new (home) Edge<View>(nv,view[i]);
00357           edge_p = (*edge_p)->next_edge_ref();
00358           ++xi; n_val++;
00359         }
00360         *edge_p = NULL;
00361       }
00362     }
00363 
00364     GECODE_AUTOSTACK(ViewNode<View>*,NULL,m,n_view);
00365     for (int i = n_view; i--; )
00366       if (!match(m,view[i]))
00367         return ES_FAILED;
00368     return ES_OK;
00369   }
00370 
00371   template <class View>
00372   forceinline void
00373   DomCtrl<View>::ViewValGraph::mark(void) {
00374     {
00375       // Marks all edges as used that are on simple paths in the graph
00376       // that start from a free (unmatched node) by depth-first-search
00377       GECODE_AUTOSTACK(ValNode<View>*,NULL,visit,n_val);
00378       
00379       // Insert all free nodes: they can be only value nodes as we
00380       // have a maximum matching covering all view nodes
00381       count++;
00382       {
00383         ValNode<View>** v = &val; 
00384         while (*v != NULL)
00385           if (!(*v)->matching()) {
00386             if ((*v)->empty()) {
00387               *v = (*v)->next_val();
00388               n_val--;
00389             } else {
00390               (*v)->min = count;
00391               visit.push(*v);
00392               v = (*v)->next_val_ref();
00393             }
00394           } else {
00395             v = (*v)->next_val_ref();
00396           }
00397       }
00398       
00399       // Invariant: only value nodes are on the stack!
00400       while (!visit.empty()) {
00401         ValNode<View>* n = visit.pop();
00402         for (Edge<View>* e = n->edge_fst(); e != n->edge_lst(); e=e->next()) {
00403           // Get the value node
00404           e->use();
00405           ViewNode<View>* x = e->view(n);
00406           if (x->min < count) {
00407             x->min = count;
00408             assert(x->edge_fst()->next() == x->edge_lst());
00409             ValNode<View>* m = x->edge_fst()->val(x);
00410             x->edge_fst()->use();
00411             if (m->min < count) {
00412               m->min = count;
00413               visit.push(m);
00414             }
00415           }
00416         }
00417       }
00418     }
00419 
00420     {
00421       GECODE_AUTOSTACK(Node<View>*,NULL,scc,n_val+n_view);
00422       GECODE_AUTOSTACK(Node<View>*,NULL,visit,n_val+n_view);
00423 
00424       count++;
00425       unsigned int cnt0 = count;
00426       unsigned int cnt1 = count;
00427 
00428       for (int i = n_view; i--; )
00429         if (view[i]->min < count) {
00430           Node<View>* w = view[i];
00431         start:
00432           w->low = w->min = cnt0++;
00433           scc.push(w);
00434           Edge<View>* e = w->edge_fst();
00435           while (e != w->edge_lst()) {
00436             if (e->dst(w)->min < count) {
00437               visit.push(w); w->iter = e;
00438               w=e->dst(w);
00439               goto start;
00440             }
00441           next:
00442             if (e->dst(w)->low < w->min)
00443               w->min = e->dst(w)->low;
00444             e = e->next();
00445           }
00446           if (w->min < w->low) {
00447             w->low = w->min;
00448           } else {
00449             Node<View>* v;
00450             do {
00451               v = scc.pop();
00452               v->comp = cnt1;
00453               v->low  = UINT_MAX;
00454             } while (v != w);
00455             cnt1++;
00456           }
00457           if (!visit.empty()) {
00458             w=visit.pop(); e=w->iter; goto next;
00459           }
00460         }
00461       count = cnt0+1;
00462     }
00463   }
00464 
00466   template <class View>
00467   class PruneVal {
00468   protected:
00470     ViewNode<View>* x;
00472     Edge<View>* e;
00473   public:
00475 
00476 
00477     PruneVal(ViewNode<View>* y);
00479 
00481 
00482 
00483     bool operator()(void) const;
00485     void operator++(void);
00487 
00489 
00490 
00491     int val(void) const;
00493   };
00494 
00495   template <class View>
00496   forceinline
00497   PruneVal<View>::PruneVal(ViewNode<View>* y)
00498     : x(y), e(y->val_edges()) {
00499     while ((e != NULL) && e->used(x))
00500       e = e->next_edge();
00501   }
00502   template <class View>
00503   forceinline bool 
00504   PruneVal<View>::operator()(void) const {
00505     return e != NULL;
00506   }
00507   template <class View>
00508   forceinline void 
00509   PruneVal<View>::operator++(void) {
00510     do {
00511       e = e->next_edge();
00512     } while ((e != NULL) && e->used(x));
00513   }
00514   template <class View>
00515   forceinline int 
00516   PruneVal<View>::val(void) const {
00517     assert(!e->used(x));
00518     return e->val(x)->val();
00519   }
00520 
00521   template <class View>
00522   forceinline ExecStatus
00523   DomCtrl<View>::ViewValGraph::tell(Space* home, bool& assigned) {
00524     assigned = false;
00525     // Tell constraints and also eliminate nodes and edges
00526     for (int i = n_view; i--; ) {
00527       ViewNode<View>* x = view[i];
00528       if (!x->edge_fst()->used(x)) {
00529         GECODE_ME_CHECK(x->view().eq(home,x->edge_fst()->val(x)->val()));
00530         x->edge_fst()->val(x)->matching(NULL);
00531         for (Edge<View>* e = x->val_edges(); e != NULL; e = e->next_edge())
00532           e->unlink();
00533         view[i] = view[--n_view];
00534         assigned = true;
00535       } else {
00536         PruneVal<View> pv(view[i]);
00537         GECODE_ME_CHECK(view[i]->view().minus_v(home,pv,false));
00538       }
00539     }
00540     return ES_OK;
00541   }
00542 
00543   template <class View>
00544   forceinline void
00545   DomCtrl<View>::ViewValGraph::purge(void) {
00546     if (count > (UINT_MAX >> 1)) {
00547       count = 1;
00548       for (int i=n_view; i--; )
00549         view[i]->min = 0;
00550       for (ValNode<View>* v = val; v != NULL; v = v->next_val())
00551         v->min = 0;
00552     }
00553   }
00554 
00555   template <class View>
00556   bool
00557   DomCtrl<View>::ViewValGraph::sync(void) {
00558     // Stack for view nodes to be rematched
00559     GECODE_AUTOSTACK(ViewNode<View>*,NULL,re,n_view);
00560     // Synchronize nodes
00561     for (int i = n_view; i--; ) {
00562       ViewNode<View>* x = view[i];
00563       if (x->view().assigned()) {
00564         x->edge_fst()->val(x)->matching(NULL);
00565         for (Edge<View>* e = x->val_edges(); e != NULL; e = e->next_edge())
00566           e->unlink();
00567         view[i] = view[--n_view];
00568       } else {
00569         ViewRanges<View> r(x->view());
00570         Edge<View>*  m = x->edge_fst();      // Matching edge
00571         Edge<View>** p = x->val_edges_ref();
00572         Edge<View>*  e = *p;
00573         do {
00574           while (e->val(x)->val() < r.min()) {
00575             // Skip edge
00576             e->unlink(); e->mark();
00577             e = e->next_edge();
00578           }
00579           *p = e;
00580           assert(r.min() == e->val(x)->val());
00581           // This edges must be kept
00582           for (unsigned int j=r.width(); j--; ) {
00583             e->free();
00584             p = e->next_edge_ref();
00585             e = e->next_edge();
00586           }
00587           ++r;
00588         } while (r());
00589         *p = NULL;
00590         while (e != NULL) {
00591           e->unlink(); e->mark();
00592           e = e->next_edge();
00593         }
00594         if (m->marked()) {
00595           // Matching has been deleted!
00596           m->val(x)->matching(NULL);
00597           re.push(x);
00598         }
00599       }
00600     }
00601     GECODE_AUTOSTACK(ViewNode<View>*,NULL,m,n_view);
00602     while (!re.empty())
00603       if (!match(m,re.pop()))
00604         return false;
00605     return true;
00606   }
00607 
00608 
00609 
00610   /*
00611    * The propagation controller
00612    *
00613    */
00614 
00615   template <class View>
00616   forceinline
00617   DomCtrl<View>::DomCtrl(void) {}
00618 
00619   template <class View>
00620   forceinline bool
00621   DomCtrl<View>::available(void) {
00622     return vvg.initialized();
00623   }
00624 
00625   template <class View>
00626   forceinline ExecStatus
00627   DomCtrl<View>::init(Space* home, int n, View* x) {
00628     return vvg.init(home,n,x);
00629   }
00630 
00631   template <class View>
00632   forceinline ExecStatus
00633   DomCtrl<View>::sync(void) {
00634     vvg.purge();
00635     return vvg.sync() ? ES_OK : ES_FAILED;
00636   }
00637 
00638   template <class View>
00639   forceinline ExecStatus
00640   DomCtrl<View>::propagate(Space* home, bool& assigned) {
00641     vvg.mark();
00642     return vvg.tell(home,assigned);
00643   }
00644 
00645 
00646   /*
00647    * The propagator proper
00648    *
00649    */
00650 
00651   template <class View>
00652   forceinline
00653   Dom<View>::Dom(Space* home, ViewArray<View>& x)
00654     : NaryPropagator<View,PC_INT_DOM>(home,x) {}
00655 
00656   template <class View>
00657   ExecStatus
00658   Dom<View>::post(Space* home, ViewArray<View>& x) {
00659     if (x.size() == 2)
00660       return Rel::Nq<View>::post(home,x[0],x[1]);
00661     if (x.size() == 3)
00662       return TerDom<View>::post(home,x[0],x[1],x[2]);
00663     if (x.size() > 3) {
00664       // Do bounds propagation to make view-value graph smaller
00665       GECODE_ES_CHECK(prop_bnd<View>(home,x))
00666       (void) new (home) Dom<View>(home,x);
00667     }
00668     return ES_OK;
00669   }
00670 
00671   template <class View>
00672   void
00673   Dom<View>::post(Space* home, Reflection::VarMap& vars,
00674                   const Reflection::ActorSpec& spec) {
00675     spec.checkArity(1);
00676     ViewArray<View> x(home, vars, spec[0]);
00677     (void) new (home) Dom<View>(home, x);
00678   }
00679 
00680   template <class View>
00681   forceinline
00682   Dom<View>::Dom(Space* home, bool share, Dom<View>& p)
00683     : NaryPropagator<View,PC_INT_DOM>(home,share,p) {}
00684 
00685   template <class View>
00686   PropCost
00687   Dom<View>::cost(ModEventDelta med) const {
00688     return cost_lo(x.size(),
00689                    (View::me(med) == ME_INT_VAL)
00690                    ? PC_LINEAR_LO : PC_CUBIC_LO);
00691   }
00692 
00693   template <class View>
00694   Support::Symbol
00695   Dom<View>::ati(void) {
00696     return Reflection::mangle<View>("Gecode::Int::Distinct::Dom");
00697   }
00698 
00699   template <class View>
00700   Reflection::ActorSpec
00701   Dom<View>::spec(const Space* home, Reflection::VarMap& m) const {
00702     return NaryPropagator<View,PC_INT_DOM>::spec(home, m, ati());
00703   }
00704 
00705   template <class View>
00706   Actor*
00707   Dom<View>::copy(Space* home, bool share) {
00708     return new (home) Dom<View>(home,share,*this);
00709   }
00710 
00711   template <class View>
00712   ExecStatus
00713   Dom<View>::propagate(Space* home, ModEventDelta med) {
00714     if (View::me(med) == ME_INT_VAL) {
00715       ExecStatus es = prop_val<View,false>(home,x);
00716       GECODE_ES_CHECK(es);
00717       if (x.size() < 2)
00718         return ES_SUBSUMED(this,home);
00719       if (es == ES_FIX)
00720         return ES_FIX_PARTIAL(this,View::med(ME_INT_DOM));
00721       es = prop_bnd<View>(home,x);
00722       GECODE_ES_CHECK(es);
00723       if (x.size() < 2)
00724         return ES_SUBSUMED(this,home);
00725       es = prop_val<View,true>(home,x);
00726       GECODE_ES_CHECK(es);
00727       if (x.size() < 2)
00728         return ES_SUBSUMED(this,home);
00729       return ES_FIX_PARTIAL(this,View::med(ME_INT_DOM));
00730     }
00731 
00732     if (x.size() == 2)
00733       GECODE_REWRITE(this,Rel::Nq<View>::post(home,x[0],x[1]));
00734     if (x.size() == 3)
00735       GECODE_REWRITE(this,TerDom<View>::post(home,x[0],x[1],x[2]));
00736 
00737     if (dc.available()) {
00738       GECODE_ES_CHECK(dc.sync());
00739     } else {
00740       GECODE_ES_CHECK(dc.init(home,x.size(),&x[0]));
00741     }
00742 
00743     bool assigned;
00744     GECODE_ES_CHECK(dc.propagate(home,assigned));
00745 
00746     return ES_FIX;
00747   }
00748 
00749 }}}
00750 
00751 // STATISTICS: int-prop
00752