dlvhex
2.5.0
|
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: