dlvhex  2.1.0
include/dlvhex2/EvalGraphBuilder.h
Go to the documentation of this file.
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