Generated on Thu Mar 22 10:39:36 2012 for Gecode by doxygen 1.6.3

graph.hpp

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: 2011-09-07 16:15:16 +0200 (Wed, 07 Sep 2011) $ by $Author: schulte $
00011  *     $Revision: 12394 $
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 ViewValGraph {
00041 
00042   template<class View>
00043   forceinline
00044   Graph<View>::Graph(void)
00045     : view(NULL), val(NULL), n_view(0), n_val(0), count(1U) {}
00046 
00047   template<class View>
00048   forceinline bool
00049   Graph<View>::initialized(void) const {
00050     return view != NULL;
00051   }
00052 
00053   template<class View>
00054   forceinline void
00055   Graph<View>::init(Space& home, ViewNode<View>* x) {
00056     Edge<View>** edge_p = x->val_edges_ref();
00057     ViewValues<View> xi(x->view());
00058     ValNode<View>** v = &val;
00059     while (xi() && (*v != NULL)) {
00060       if ((*v)->val() == xi.val()) {
00061         // Value node does already exist, create new edge
00062         *edge_p = new (home) Edge<View>(*v,x);
00063         edge_p = (*edge_p)->next_edge_ref();
00064         v = (*v)->next_val_ref();
00065         ++xi;
00066       } else if ((*v)->val() < xi.val()) {
00067         // Skip to next value node
00068         v = (*v)->next_val_ref();
00069       } else {
00070         // Value node does not yet exist, create and link it
00071         ValNode<View>* nv = new (home) ValNode<View>(xi.val(),*v);
00072         *v = nv; v = nv->next_val_ref();
00073         *edge_p = new (home) Edge<View>(nv,x);
00074         edge_p = (*edge_p)->next_edge_ref();
00075         ++xi; n_val++;
00076       }
00077     }
00078     // Create missing value nodes
00079     while (xi()) {
00080       ValNode<View>* nv = new (home) ValNode<View>(xi.val(),*v);
00081       *v = nv; v = nv->next_val_ref();
00082       *edge_p = new (home) Edge<View>(nv,x);
00083       edge_p = (*edge_p)->next_edge_ref();
00084       ++xi; n_val++;
00085     }
00086     *edge_p = NULL;
00087   }
00088 
00089   template<class View>
00090   forceinline bool
00091   Graph<View>::match(ViewNodeStack& m, ViewNode<View>* x) {
00092     count++;
00093   start:
00094     // Try to find matching edge cheaply: is there a free edge around?
00095     {
00096       Edge<View>* e = x->val_edges();
00097       // This holds true as domains are never empty
00098       assert(e != NULL);
00099       do {
00100         if (!e->val(x)->matching()) {
00101           e->revert(x); e->val(x)->matching(e);
00102           // Found a matching, revert all edges on stack
00103           while (!m.empty()) {
00104             x = m.pop(); e = x->iter;
00105             e->val(x)->matching()->revert(e->val(x));
00106             e->revert(x); e->val(x)->matching(e);
00107           }
00108           return true;
00109         }
00110         e = e->next_edge();
00111       } while (e != NULL);
00112     }
00113     // No, find matching edge by augmenting path method
00114     Edge<View>* e = x->val_edges();
00115     do {
00116       if (e->val(x)->matching()->view(e->val(x))->min < count) {
00117         e->val(x)->matching()->view(e->val(x))->min = count;
00118         m.push(x); x->iter = e;
00119         x = e->val(x)->matching()->view(e->val(x));
00120         goto start;
00121       }
00122     next:
00123       e = e->next_edge();
00124     } while (e != NULL);
00125     if (!m.empty()) {
00126       x = m.pop(); e = x->iter; goto next;
00127     }
00128     // All nodes and edges unsuccessfully tried
00129     return false;
00130   }
00131 
00132   template<class View>
00133   forceinline void
00134   Graph<View>::purge(void) {
00135     if (count > (UINT_MAX >> 1)) {
00136       count = 1;
00137       for (int i=n_view; i--; )
00138         view[i]->min = 0;
00139       for (ValNode<View>* v = val; v != NULL; v = v->next_val())
00140         v->min = 0;
00141     }
00142   }
00143 
00144   template<class View>
00145   forceinline void
00146   Graph<View>::scc(Space& home) {
00147     Region r(home);
00148 
00149     Support::StaticStack<Node<View>*,Region> scc(r,n_val+n_view);
00150     Support::StaticStack<Node<View>*,Region> visit(r,n_val+n_view);
00151       
00152     count++;
00153     unsigned int cnt0 = count;
00154     unsigned int cnt1 = count;
00155     
00156     for (int i = n_view; i--; )
00157       /*
00158        * The following test is subtle: for scc, the test should be:
00159        *   view[i]->min < count
00160        * However, if view[i] < count-1, then the node has already been
00161        * reached on a path and all edges connected to the node have been
00162        * marked anyway! So just ignore this node altogether for scc.
00163        */ 
00164       if (view[i]->min < count-1) {
00165         Node<View>* w = view[i];
00166       start:
00167         w->low = w->min = cnt0++;
00168         scc.push(w);
00169         Edge<View>* e = w->edge_fst();
00170         while (e != w->edge_lst()) {
00171           if (e->dst(w)->min < count) {
00172             visit.push(w); w->iter = e;
00173             w=e->dst(w);
00174             goto start;
00175           }
00176         next:
00177           if (e->dst(w)->low < w->min)
00178             w->min = e->dst(w)->low;
00179           e = e->next();
00180         }
00181         if (w->min < w->low) {
00182           w->low = w->min;
00183         } else {
00184           Node<View>* v;
00185           do {
00186             v = scc.pop();
00187             v->comp = cnt1;
00188             v->low  = UINT_MAX;
00189           } while (v != w);
00190           cnt1++;
00191         }
00192         if (!visit.empty()) {
00193           w=visit.pop(); e=w->iter; goto next;
00194         }
00195       }
00196     count = cnt0+1;
00197   }
00198 
00199 
00200 }}}
00201 
00202 // STATISTICS: int-prop