dlvhex  2.5.0
include/dlvhex2/CAUAlgorithms.h
Go to the documentation of this file.
00001 /* dlvhex -- Answer-Set Programming with external interfaces.
00002  * Copyright (C) 2005-2007 Roman Schindlauer
00003  * Copyright (C) 2006-2015 Thomas Krennwallner
00004  * Copyright (C) 2009-2016 Peter Schüller
00005  * Copyright (C) 2011-2016 Christoph Redl
00006  * Copyright (C) 2015-2016 Tobias Kaminski
00007  * Copyright (C) 2015-2016 Antonius Weinzierl
00008  *
00009  * This file is part of dlvhex.
00010  *
00011  * dlvhex is free software; you can redistribute it and/or modify it
00012  * under the terms of the GNU Lesser General Public License as
00013  * published by the Free Software Foundation; either version 2.1 of
00014  * the License, or (at your option) any later version.
00015  *
00016  * dlvhex is distributed in the hope that it will be useful, but
00017  * WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00019  * Lesser General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU Lesser General Public
00022  * License along with dlvhex; if not, write to the Free Software
00023  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
00024  * 02110-1301 USA.
00025  */
00026 
00034 #ifndef CAUALGORITHMS_HPP_INCLUDED__28092010
00035 #define CAUALGORITHMS_HPP_INCLUDED__28092010
00036 
00037 #include "Logger.h"
00038 #include "Printhelpers.h"
00039 #include "EvalGraph.h"
00040 #include "ModelGraph.h"
00041 #include "ModelGenerator.h"
00042 
00043 #include <boost/graph/depth_first_search.hpp>
00044 #include <boost/graph/two_bit_color_map.hpp>
00045 #include <boost/graph/reverse_graph.hpp>
00046 
00048 namespace CAUAlgorithms
00049 {
00050     typedef std::set<int> Ancestry;
00051 
00056     typedef boost::vector_property_map<Ancestry> AncestryPropertyMap;
00057 
00063     template<typename EvalGraphT>
00064         void findCAUs(
00065         std::set<typename EvalGraphT::EvalUnit>& caus,
00066         const EvalGraphT& eg,
00067         typename EvalGraphT::EvalUnit u,
00068         AncestryPropertyMap& apm);
00069 
00076     template<typename EvalGraphT>
00077         void findCAUs(
00078         std::set<typename EvalGraphT::EvalUnit>& caus,
00079         const EvalGraphT& eg,
00080         typename EvalGraphT::EvalUnit u)
00081         { AncestryPropertyMap apm; return findCAUs(caus, eg, u, apm); }
00082 
00085     DLVHEX_EXPORT void logAPM(const AncestryPropertyMap& apm);
00086 
00087     //
00088     // "Join relevant" are those units where simple iteration over omodels is
00089     // not allowed, therefore everything with a CAU above is join relevant. A
00090     // CAU itself is only join relevant if it has a CAU above.
00091     //
00092 
00093     typedef boost::vector_property_map<bool> JoinRelevancePropertyMap;
00094 
00095     // initialize with false (ensure one-time allocation)
00102     template<typename EvalGraphT>
00103         void initJoinRelevance(
00104         JoinRelevancePropertyMap& jr,
00105         const EvalGraphT& eg);
00106 
00117     template<typename EvalGraphT>
00118         void markJoinRelevance(
00119         JoinRelevancePropertyMap& jr,
00120         const EvalGraphT& eg,
00121         typename EvalGraphT::EvalUnit u,
00122         const std::set<typename EvalGraphT::EvalUnit>& caus,
00123         const AncestryPropertyMap& apm);
00124 
00125     DLVHEX_EXPORT void logJRPM(const JoinRelevancePropertyMap& jr);
00126 }                                // namespace CAUAlgorithms
00127 
00128 
00129 // implementation
00130 
00131 namespace CAUAlgorithms
00132 {
00133 
00134     template<typename Graph>
00135         class AncestryMarkingVisitor:
00136     public boost::default_dfs_visitor
00137     {
00138         public:
00139             typedef typename Graph::vertex_descriptor Vertex;
00140             typedef typename Graph::edge_descriptor Edge;
00141 
00142         public:
00143             AncestryMarkingVisitor(AncestryPropertyMap& apm, std::set<Vertex>& caus):
00144             apm(apm), caus(caus) {}
00145 
00146             void examine_edge(Edge e, const Graph& g) const
00147             {
00148                 Vertex from = boost::source(e, g);
00149                 Vertex to = boost::target(e, g);
00150 
00151                 // join order is stored in an internal property
00152                 unsigned joinOrder = g[e].joinOrder;
00153                 DBGLOG(DBG,"examine edge " << from << " -> " << to << " joinOrder " << joinOrder);
00154 
00155                 Ancestry& afrom = apm[from];
00156                 Ancestry& ato = apm[to];
00157                 Ancestry propagate;
00158                 if( afrom.empty() ) {
00159                     // directly above first vertex -> initialize
00160                     propagate.insert(joinOrder);
00161                 }
00162                 else {
00163                     // propagate from previous vertex
00164                     propagate = afrom;
00165                 }
00166 
00167                 if( ato.empty() ) {
00168                     // just copy (fast way out)
00169                     ato = propagate;
00170                 }
00171                 else {
00172                     // check if we hit something new
00173                     Ancestry newancestry;
00174                     // newancestry = ato - afrom
00175                     std::set_difference(
00176                         ato.begin(), ato.end(),
00177                         afrom.begin(), afrom.end(),
00178                         std::insert_iterator<Ancestry>(newancestry, newancestry.begin()));
00179                     if( !newancestry.empty() ) {
00180                         LOG(MODELB,"found new ancestry: " << printset(newancestry));
00181                         caus.insert(to);
00182                     }
00183                     ato.insert(afrom.begin(), afrom.end());
00184                 }
00185             }
00186 
00187         protected:
00188             AncestryPropertyMap& apm;
00189             std::set<Vertex>& caus;
00190     };
00191 
00192     // the first parameter is the unit for which we want to find the CAUs (common ancestor units)
00193     // the second parameter is the ancestry map used for finding the CAUs
00194     // (this is required for a subsequent call to markJoinRelevance and for debugging)
00195     template<typename EvalGraphT>
00196         void
00197         findCAUs(
00198         std::set<typename EvalGraphT::EvalUnit>& caus,
00199         const EvalGraphT& eg,
00200         typename EvalGraphT::EvalUnit u,
00201     AncestryPropertyMap& apm) {
00202         LOG_VSCOPE(MODELB,"findCAUs",u,true);
00203 
00204         typedef EvalGraphT EvalGraph;
00205         typedef typename EvalGraphT::EvalUnit EvalUnit;
00206 
00207         // for each predecessor p of u,
00208         // do a DFS in the eval graph, marking ancestry with the join order of p
00209         // if we find an ancestry different from the one of p,
00210         // and we did not find it before in that DFS run, we have found a CAU
00211 
00212         AncestryMarkingVisitor<typename EvalGraphT::EvalGraphInt>
00213             visitor(apm, caus);
00214 
00215         boost::two_bit_color_map<boost::identity_property_map>
00216             cmap(eg.countEvalUnits());
00217 
00218         boost::depth_first_visit(
00219             eg.getInt(), u, visitor, cmap);
00220     }
00221 
00222     template<typename Graph>
00223         class RelevanceMarkingVisitor:
00224     public boost::default_dfs_visitor
00225     {
00226         public:
00227             typedef typename Graph::vertex_descriptor Vertex;
00228             typedef typename Graph::edge_descriptor Edge;
00229 
00230         public:
00231             RelevanceMarkingVisitor(
00232                 const AncestryPropertyMap& apm,
00233                 JoinRelevancePropertyMap& jr,
00234                 Vertex donotmark):
00235             apm(apm), jr(jr), donotmark(donotmark) {}
00236 
00237             template<typename G>
00238                 void discover_vertex(Vertex v, const G& g) const
00239             {
00240                 if( v != donotmark && !apm[v].empty() )
00241                     jr[v] = true;
00242             }
00243 
00244         protected:
00245             const AncestryPropertyMap& apm;
00246             JoinRelevancePropertyMap& jr;
00247             Vertex donotmark;
00248     };
00249 
00250     // initialize with false (ensure one-time allocation)
00251     template<typename EvalGraphT>
00252         void initJoinRelevance(
00253         JoinRelevancePropertyMap& jr,
00254     const EvalGraphT& eg) {
00255         // initialize all from jr at once by initializing last+1 one
00256         jr[eg.countEvalUnits()] = false;
00257 
00258         typedef typename EvalGraphT::EvalUnitIterator EvalUnitIterator;
00259         EvalUnitIterator it, end;
00260         for(boost::tie(it, end) = eg.getEvalUnits(); it != end; ++it) {
00261             jr[*it] = false;
00262         }
00263     }
00264 
00265     // given the results of findCAUs(caus, eg, u),
00266     // mark all units between u and elements of caus
00267     // as relevant (true), others as irrelevant (false)
00268     // (do this by going from caus along a DFS through the reversed graph,
00269     // marking everything that has an ancestry as relevant)
00270     template<typename EvalGraphT>
00271         void markJoinRelevance(
00272         JoinRelevancePropertyMap& jr,
00273         const EvalGraphT& eg,
00274         typename EvalGraphT::EvalUnit u,
00275         const std::set<typename EvalGraphT::EvalUnit>& caus,
00276     const AncestryPropertyMap& apm) {
00277         typedef typename EvalGraphT::EvalGraphInt GraphInt;
00278         typedef boost::reverse_graph<GraphInt, const GraphInt&> RGraphInt;
00279         typedef typename EvalGraphT::EvalUnit EvalUnit;
00280 
00281         // reverse eval graph
00282         RGraphInt reg(eg.getInt());
00283 
00284         // mark all irrelevant
00285         initJoinRelevance(jr, eg);
00286 
00287         // do DFS starting from each CAU
00288         typename std::set<EvalUnit>::const_iterator cau;
00289         for(cau = caus.begin(); cau != caus.end(); ++cau) {
00290             DBGLOG(DBG,"marking relevance from cau " << *cau);
00291             RelevanceMarkingVisitor<typename EvalGraphT::EvalGraphInt>
00292                 visitor(apm, jr, *cau);
00293             boost::two_bit_color_map<boost::identity_property_map>
00294                 cmap(eg.countEvalUnits());
00295             boost::depth_first_visit(
00296                 reg, *cau, visitor, cmap);
00297             logJRPM(jr);
00298         }
00299     }
00300 
00301 }                                // namespace CAUAlgorithms
00302 #endif                           // CAUALGORITHMS_HPP_INCLUDED__28092010
00303 
00304 // vim:expandtab:ts=4:sw=4:
00305 // mode: C++
00306 // End: