|
dlvhex
2.1.0
|
00001 /* dlvhex -- Answer-Set Programming with external interfaces. 00002 * Copyright (C) 2005, 2006, 2007 Roman Schindlauer 00003 * Copyright (C) 2006, 2007, 2008, 2009, 2010 Thomas Krennwallner 00004 * Copyright (C) 2009, 2010 Peter Schüller 00005 * 00006 * This file is part of dlvhex. 00007 * 00008 * dlvhex is free software; you can redistribute it and/or modify it 00009 * under the terms of the GNU Lesser General Public License as 00010 * published by the Free Software Foundation; either version 2.1 of 00011 * the License, or (at your option) any later version. 00012 * 00013 * dlvhex is distributed in the hope that it will be useful, but 00014 * WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00016 * Lesser General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU Lesser General Public 00019 * License along with dlvhex; if not, write to the Free Software 00020 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 00021 * 02110-1301 USA. 00022 */ 00023 00031 #ifndef EVAL_GRAPH_BUILDER_HPP_INCLUDED__03112010 00032 #define EVAL_GRAPH_BUILDER_HPP_INCLUDED__03112010 00033 00034 #include "dlvhex2/FinalEvalGraph.h" 00035 #include "dlvhex2/ComponentGraph.h" 00036 #include "dlvhex2/ASPSolverManager.h" 00037 #include "dlvhex2/Logger.h" 00038 00039 #include <boost/range/iterator_range.hpp> 00040 #include <boost/concept/assert.hpp> 00041 #include <boost/concept_check.hpp> 00042 #include <boost/graph/filtered_graph.hpp> 00043 #include <boost/bimap/bimap.hpp> 00044 #include <boost/bimap/unordered_set_of.hpp> 00045 #include <boost/bimap/unordered_multiset_of.hpp> 00046 00047 DLVHEX_NAMESPACE_BEGIN 00048 00049 class ProgramCtx; 00050 00059 //template<typename EvalGraphT> 00060 // TODO make this a template for EvalGraphT and ComponentGraphT, for faster prototyping we use fixed types for these graphs 00061 class EvalGraphBuilder 00062 { 00064 // types 00066 public: 00067 typedef FinalEvalGraph EvalGraphT; 00068 typedef EvalGraphT::EvalUnit EvalUnit; 00069 typedef ComponentGraph::Component Component; 00070 typedef ComponentGraph::Dependency Dependency; 00071 00072 protected: 00073 typedef ComponentGraph::ComponentSet ComponentSet; 00074 typedef ComponentGraph::ComponentInfo ComponentInfo; 00075 struct DependencyInfo: 00076 public ComponentGraph::DependencyInfo 00077 { 00078 // this is not a property of a graph, 00079 // we use this when we calculate the dependencies of a new unit 00080 // and for that we need to know on which units it depends 00081 EvalUnit dependsOn; 00082 DependencyInfo(EvalUnit dependsOn, const ComponentGraph::DependencyInfo& parent): 00083 ComponentGraph::DependencyInfo(parent), dependsOn(dependsOn) {} 00084 }; 00085 00086 protected: 00087 // we use identity as hash function as eval units are distinct unsigned ints 00088 00089 BOOST_CONCEPT_ASSERT((boost::Convertible<Component, void*>)); 00090 BOOST_CONCEPT_ASSERT((boost::Convertible<EvalUnit, unsigned>)); 00091 00092 struct identity { 00093 inline unsigned operator()(unsigned u) const { return u; } 00094 }; 00095 00096 // bidirectional mapping: 00097 // set of components -> one eval unit 00098 // set of components <- one eval unit 00099 // constraint components that have been pushed up are ignored here 00100 // (nothing can depend on them, and they are not "used" until all their 00101 // dependencies have been fulfilled) 00102 typedef boost::bimaps::bimap< 00103 boost::bimaps::unordered_set_of<Component>, 00104 boost::bimaps::unordered_multiset_of<EvalUnit, identity > 00105 > ComponentEvalUnitMapping; 00106 00107 protected: 00108 // for subgraph of component graph that still needs to be put into eval units: 00109 // 00110 // we cannot use subgraph to keep track of the rest of the component graph, 00111 // because subgraph does not allow for removing vertices and is furthermore 00112 // broken for bundled properties (see boost bugtracker) 00113 // 00114 // therefore we use the mapping to keep track of used components 00115 // and we filter the graph using boost::filtered_graph 00116 // (components are unsigned ints as verified by the following concept check) 00117 struct UnusedVertexFilter 00118 { 00119 // unfortunately, this predicate must be default constructible 00120 UnusedVertexFilter(): ceum(0) {} 00121 UnusedVertexFilter(const ComponentEvalUnitMapping* ceum): ceum(ceum) {} 00122 UnusedVertexFilter(const UnusedVertexFilter& other): ceum(other.ceum) {} 00123 UnusedVertexFilter& operator=(const UnusedVertexFilter& other) 00124 { ceum = other.ceum; return *this; } 00125 // return true if vertex is still in graph -> return true if not mapped yet 00126 bool operator()(Component comp) const 00127 { assert(ceum); return ceum->left.find(comp) == ceum->left.end(); } 00128 const ComponentEvalUnitMapping* ceum; 00129 }; 00130 struct UnusedEdgeFilter 00131 { 00132 // unfortunately, this predicate must be default constructible 00133 UnusedEdgeFilter(): cg(0), ceum(0) {} 00134 UnusedEdgeFilter(const ComponentGraph* const cg, 00135 const ComponentEvalUnitMapping* const ceum): cg(cg), ceum(ceum) {} 00136 UnusedEdgeFilter(const UnusedEdgeFilter& other): cg(other.cg), ceum(other.ceum) {} 00137 UnusedEdgeFilter& operator=(const UnusedEdgeFilter& other) 00138 { cg = other.cg; ceum = other.ceum; return *this; } 00139 bool operator()(Dependency dep) const 00140 { assert(cg && ceum); 00141 return 00142 (ceum->left.find(cg->targetOf(dep)) == ceum->left.end()) && 00143 (ceum->left.find(cg->sourceOf(dep)) == ceum->left.end()); } 00144 const ComponentGraph* cg; 00145 const ComponentEvalUnitMapping* ceum; 00146 }; 00147 00148 public: 00149 typedef boost::filtered_graph<ComponentGraph::Graph, 00150 UnusedEdgeFilter, UnusedVertexFilter> ComponentGraphRest; 00151 00153 // members 00155 protected: 00156 // overall program context 00157 ProgramCtx& ctx; 00158 // component graph (this is an input -> const) 00159 const ComponentGraph& cg; 00160 // eval graph 00161 EvalGraphT& eg; 00162 // configuration for model generator factory 00163 ASPSolverManager::SoftwareConfigurationPtr externalEvalConfig; 00164 00165 // mapping of nonshared components to eval units 00166 ComponentEvalUnitMapping mapping; 00167 00168 // 00169 // subgraph of component graph that still needs to be put into eval units 00170 // 00171 // (see comment above) 00172 UnusedEdgeFilter unusedEdgeFilter; 00173 UnusedVertexFilter unusedVertexFilter; 00174 // induced subgraph of cg: 00175 // nodes not in mapping are part of this graph 00176 // edges where both nodes are not in mapping are part of this graph 00177 // 00178 // (the sources of boost::filtered_graph suggest that after an update to 00179 // usedNodes, iterators of cgrest should not be reused, but the graph 00180 // need not be reconstructed) 00181 ComponentGraphRest cgrest; 00182 00184 // methods 00186 public: 00187 EvalGraphBuilder( 00188 ProgramCtx& ctx, ComponentGraph& cg, EvalGraphT& eg, 00189 ASPSolverManager::SoftwareConfigurationPtr externalEvalConfig); 00190 virtual ~EvalGraphBuilder(); 00191 00192 // 00193 // accessors 00194 // 00195 inline const EvalGraphT& getEvalGraph() const { return eg; } 00196 //inline ComponentGraph& getComponentGraph() { return cg; } 00197 inline const ComponentGraph& getComponentGraph() const { return cg; } 00198 // returns a graph consisting of all components that still need to be built into some evaluation unit 00199 inline const ComponentGraphRest& getComponentGraphRest() const { return cgrest; } 00200 00201 // returns the registry (useful for printing, cannot do this inline as ProgramCtx depends on this header) 00202 RegistryPtr registry(); 00203 00204 // 00205 // modifiers 00206 // 00207 00208 // this methods modifies the eval graph 00209 // 00210 // it asserts that all requirements for evaluation units are fulfilled 00211 // it adds an evaluation unit created from given nodes, including dependencies 00212 // 00213 // TODO add ordered unit dependencies 00214 // TODO use ComponentRange 00215 //template<typename NodeRange, typename UnitRange> 00216 //virtual EvalUnit createEvalUnit( 00217 // NodeRange nodes, UnitRange orderedDependencies); 00218 // 00219 // comps = list of components to directly put into eval unit 00220 // ccomps = list of components to copy into eval unit 00221 // (these copied components may only contain constraints, and these must obey the 00222 // constraint pushing restrictions (this will be asserted by createEvalUnit)) 00223 virtual EvalUnit createEvalUnit( 00224 const std::list<Component>& comps, const std::list<Component>& ccomps); 00225 00226 protected: 00227 // prepare to collapse given components into evaluation unit 00228 // prepare collapse incoming dependencies 00229 // create dependencies and properties of dependencies 00230 // create properties of component 00231 // asserts that this operation does not make the DAG cyclic 00232 void calculateNewEvalUnitInfos( 00233 const ComponentSet& comps, const ComponentSet& ccomps, 00234 std::list<DependencyInfo>& newUnitDependsOn, 00235 ComponentInfo& newUnitInfo); 00236 }; 00237 typedef boost::shared_ptr<EvalGraphBuilder> EvalGraphBuilderPtr; 00238 00239 DLVHEX_NAMESPACE_END 00240 00241 #endif // EVAL_GRAPH_BUILDER_HPP_INCLUDED__03112010