Generated on Tue Apr 18 10:21:52 2017 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, 2011
00008  *
00009  *  Last modified:
00010  *     $Date: 2016-06-18 14:20:49 +0200 (Sat, 18 Jun 2016) $ by $Author: schulte $
00011  *     $Revision: 15118 $
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 namespace Gecode { namespace Int { namespace NValues {
00039 
00040   forceinline
00041   Graph::Graph(void)
00042     : n_matched(0) {}
00043 
00044   forceinline int
00045   Graph::size(void) const {
00046     return n_matched;
00047   }
00048 
00049   forceinline void
00050   Graph::init(Space& home, const ValSet& vs, const ViewArray<IntView>& x) {
00051     using namespace ViewValGraph;
00052     n_view = x.size() + vs.size();
00053     view = home.alloc<ViewNode<IntView>*>(n_view);
00054 
00055     // Create nodes corresponding to the value set vs
00056     {
00057       int i = x.size();
00058       ValSet::Ranges vsr(vs);
00059       ValNode<IntView>** v = &val;
00060       for (Iter::Ranges::ToValues<ValSet::Ranges> n(vsr); n(); ++n) {
00061         // Create view node
00062         view[i] = new (home) ViewNode<IntView>();
00063         // Create and link value node
00064         ValNode<IntView>* nv = new (home) ValNode<IntView>(n.val());
00065         *v = nv; v = nv->next_val_ref();
00066         // Create and link single edge
00067         Edge<IntView>** e = view[i]->val_edges_ref();
00068         *e = new (home) Edge<IntView>(nv,view[i],NULL);
00069         // Match edge
00070         (*e)->revert(view[i]); nv->matching(*e);
00071         i++;
00072       }
00073       *v = NULL;
00074       n_val = vs.size();
00075       n_matched = vs.size();
00076       assert(i - x.size() == vs.size());
00077     }
00078 
00079     // Initialize real view nodes
00080     for (int i=x.size(); i--; ) {
00081       view[i] = new (home) ViewNode<IntView>(x[i]);
00082       ViewValGraph::Graph<IntView>::init(home,view[i]);
00083     }
00084 
00085     // Match the real view nodes, if possible
00086     Region r(home);
00087     ViewNodeStack m(r,n_view);
00088     for (int i = x.size(); i--; )
00089       if (match(m,view[i]))
00090         n_matched++;
00091   }
00092 
00093   forceinline void
00094   Graph::sync(Space& home) {
00095     using namespace ViewValGraph;
00096     Region r(home);
00097 
00098     // Whether to rematch
00099     bool rematch = false;
00100 
00101     // Synchronize nodes
00102     for (int i = n_view; i--; ) {
00103       ViewNode<IntView>* x = view[i];
00104       // Skip faked view nodes, they correspond to values in the value set
00105       if (!x->fake()) {
00106         if (x->changed()) {
00107           ViewRanges<IntView> rx(x->view());
00108           Edge<IntView>*  m = x->matched() ? x->edge_fst() : NULL;
00109           Edge<IntView>** p = x->val_edges_ref();
00110           Edge<IntView>*  e = *p;
00111           do {
00112             while (e->val(x)->val() < rx.min()) {
00113               // Skip edge
00114               e->unlink(); e->mark();
00115               e = e->next_edge();
00116             }
00117             *p = e;
00118             assert(rx.min() == e->val(x)->val());
00119             // This edges must be kept
00120             for (unsigned int j=rx.width(); j--; ) {
00121               e->free();
00122               p = e->next_edge_ref();
00123               e = e->next_edge();
00124             }
00125             ++rx;
00126           } while (rx());
00127           *p = NULL;
00128           while (e != NULL) {
00129             e->unlink(); e->mark();
00130             e = e->next_edge();
00131           }
00132           if ((m != NULL) && m->marked()) {
00133             // Matching has been deleted!
00134             m->val(x)->matching(NULL);
00135             rematch = true;
00136             n_matched--;
00137           }
00138         } else {
00139           // Just free edges
00140           for (Edge<IntView>* e=x->val_edges(); e != NULL; e = e->next_edge())
00141             e->free();
00142         }
00143       }
00144     }
00145 
00146     if (rematch) {
00147       ViewNodeStack m(r,n_view);
00148       for (int i = n_view; i--; )
00149         if (!view[i]->matched() && match(m,view[i]))
00150           n_matched++;
00151     }
00152   }
00153 
00154   forceinline bool
00155   Graph::mark(Space& home) {
00156     using namespace ViewValGraph;
00157     Region r(home);
00158 
00159     int n_view_visited = 0;
00160     {
00161       // Marks all edges as used that are on simple paths in the graph
00162       // that start from a free value node by depth-first-search
00163       Support::StaticStack<ValNode<IntView>*,Region> visit(r,n_val);
00164 
00165       // Insert all free value nodes
00166       count++;
00167       {
00168         ValNode<IntView>** v = &val;
00169         while (*v != NULL)
00170           // Is the node free?
00171           if (!(*v)->matching()) {
00172             // Eliminate empty value nodes
00173             if ((*v)->empty()) {
00174               *v = (*v)->next_val();
00175               n_val--;
00176             } else {
00177               (*v)->min = count;
00178               visit.push(*v);
00179               v = (*v)->next_val_ref();
00180             }
00181           } else {
00182             v = (*v)->next_val_ref();
00183           }
00184       }
00185 
00186       // Invariant: only value nodes are on the stack!
00187       while (!visit.empty()) {
00188         ValNode<IntView>* n = visit.pop();
00189         for (Edge<IntView>* e = n->edge_fst(); e != n->edge_lst();
00190              e = e->next()) {
00191           // Is the view node is matched: the path must be alternating!
00192           ViewNode<IntView>* x = e->view(n);
00193           if (x->matched()) {
00194             // Mark the edge as used
00195             e->use();
00196             if (x->min < count) {
00197               n_view_visited++;
00198               x->min = count;
00199               assert(x->edge_fst()->next() == x->edge_lst());
00200               ValNode<IntView>* m = x->edge_fst()->val(x);
00201               x->edge_fst()->use();
00202               if (m->min < count) {
00203                 m->min = count;
00204                 visit.push(m);
00205               }
00206             }
00207           }
00208         }
00209       }
00210 
00211     }
00212 
00213     if (n_view_visited < n_view) {
00214       // Mark all edges as used starting from a free view node on
00215       // an alternating path by depth-first search.
00216       Support::StaticStack<ViewNode<IntView>*,Region> visit(r,n_view);
00217 
00218       // Insert all free view nodes
00219       count++;
00220       for (int i = n_view; i--; )
00221         if (!view[i]->matched()) {
00222           view[i]->min = count;
00223           visit.push(view[i]);
00224         }
00225 
00226       // Invariant: only view nodes are on the stack!
00227       while (!visit.empty()) {
00228         n_view_visited++;
00229         ViewNode<IntView>* x = visit.pop();
00230         for (Edge<IntView>* e = x->val_edges(); e != NULL; e = e->next_edge())
00231           // Consider only free edges
00232           if (e != x->edge_fst()) {
00233             ValNode<IntView>* n = e->val(x);
00234             // Is there a matched edge from the value node to a view node?
00235             if (n->matching() != NULL) {
00236               e->use();
00237               n->matching()->use();
00238               ViewNode<IntView>* y = n->matching()->view(n);
00239               if (y->min < count) {
00240                 y->min = count;
00241                 visit.push(y);
00242               }
00243             }
00244           }
00245       }
00246 
00247     }
00248 
00249     if (n_view_visited < n_view) {
00250       scc(home);
00251       return true;
00252     } else {
00253       return false;
00254     }
00255   }
00256 
00257   forceinline ExecStatus
00258   Graph::prune(Space& home) {
00259     using namespace ViewValGraph;
00260     // Tell constraints and also eliminate nodes and edges
00261     for (int i = n_view; i--; ) {
00262       ViewNode<IntView>* x = view[i];
00263       if (!x->fake()) {
00264         if (x->matched() && !x->edge_fst()->used(x)) {
00265           GECODE_ME_CHECK(x->view().eq(home,x->edge_fst()->val(x)->val()));
00266           x->edge_fst()->val(x)->matching(NULL);
00267           for (Edge<IntView>* e = x->val_edges(); e != NULL; e=e->next_edge())
00268             e->unlink();
00269           view[i] = view[--n_view];
00270         } else {
00271           IterPruneVal<IntView> pv(x);
00272           GECODE_ME_CHECK(x->view().minus_v(home,pv,false));
00273         }
00274       }
00275     }
00276 
00277     return ES_OK;
00278   }
00279 
00280 }}}
00281 
00282 // STATISTICS: int-prop
00283