dlvhex  2.5.0
include/dlvhex2/LiberalSafetyChecker.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 
00035 #ifndef LIBERALSAFETYCHECKER_H_
00036 #define LIBERALSAFETYCHECKER_H_
00037 
00038 #include "dlvhex2/PlatformDefinitions.h"
00039 #include "dlvhex2/fwd.h"
00040 #include "dlvhex2/Logger.h"
00041 #include "dlvhex2/ID.h"
00042 
00043 #include <boost/graph/graph_traits.hpp>
00044 #include <boost/graph/adjacency_list.hpp>
00045 #include <boost/shared_ptr.hpp>
00046 #include <boost/foreach.hpp>
00047 #include <boost/intrusive/unordered_set.hpp>
00048 #include <boost/multi_index/member.hpp>
00049 #include <boost/multi_index/hashed_index.hpp>
00050 
00051 DLVHEX_NAMESPACE_BEGIN
00052 
00053 class LiberalSafetyChecker;
00054 
00055 /*
00056  * Base class for safety plugins which may integrate application-specific safety criteria.
00057  */
00058 class DLVHEX_EXPORT LiberalSafetyPlugin
00059 {
00060     protected:
00062         LiberalSafetyChecker& lsc;
00063 
00064     public:
00067         LiberalSafetyPlugin(LiberalSafetyChecker& lsc) : lsc(lsc){}
00068 
00073         virtual void run() = 0;
00074 
00075         typedef boost::shared_ptr<LiberalSafetyPlugin> Ptr;
00076 };
00077 typedef LiberalSafetyPlugin::Ptr LiberalSafetyPluginPtr;
00078 
00079 /*
00080  * Factory for safety plugins.
00081  */
00082 class DLVHEX_EXPORT LiberalSafetyPluginFactory
00083 {
00084     public:
00088         virtual LiberalSafetyPluginPtr create(LiberalSafetyChecker& lsc) = 0;
00089         typedef boost::shared_ptr<LiberalSafetyPluginFactory> Ptr;
00090 };
00091 typedef LiberalSafetyPluginFactory::Ptr LiberalSafetyPluginFactoryPtr;
00092 
00094 class DLVHEX_EXPORT LiberalSafetyChecker
00095 {
00096     public:
00098         struct Attribute : private ostream_printable<Attribute>
00099         {
00101             enum Type
00102             {
00104                 Ordinary,
00106                 External
00107             };
00109             RegistryPtr reg;
00111             Type type;
00113             ID eatomID;
00115             ID predicate;
00117             std::vector<ID> inputList;
00119             ID ruleID;
00121             bool input;
00123             int argIndex;
00124 
00128             bool operator==(const Attribute& at2) const;
00132             bool operator<(const Attribute& at2) const;
00136             std::ostream& print(std::ostream& o) const;
00137         };
00138 
00139         typedef boost::adjacency_list<boost::setS, boost::vecS, boost::bidirectionalS, Attribute > Graph;
00140         typedef boost::graph_traits<Graph> Traits;
00141 
00142         typedef Graph::vertex_descriptor Node;
00143         typedef Graph::edge_descriptor Dependency;
00144         typedef Traits::vertex_iterator NodeIterator;
00145         typedef Traits::edge_iterator DependencyIterator;
00146         typedef Traits::out_edge_iterator PredecessorIterator;
00147         typedef Traits::in_edge_iterator SuccessorIterator;
00148 
00149                                  // stores rule ID and variable ID
00150         typedef std::pair<ID, ID> VariableLocation;
00151                                  // stores rule ID and atom ID
00152         typedef std::pair<ID, ID> AtomLocation;
00153 
00155         RegistryPtr reg;
00157         const std::vector<ID>& idb;
00158 
00159     private:
00161         Graph ag;
00163         boost::unordered_map<ID, std::vector<Attribute> > attributesOfPredicate;
00164         struct NodeInfoTag {};
00166         struct NodeMappingInfo
00167         {
00168             Attribute at;
00169             Node node;
00170             NodeMappingInfo(Attribute at, Node node): at(at), node(node) {}
00171         };
00172         typedef boost::multi_index_container<
00173             NodeMappingInfo,
00174             boost::multi_index::indexed_by<
00175             boost::multi_index::hashed_unique<
00176             boost::multi_index::tag<NodeInfoTag>,
00177             BOOST_MULTI_INDEX_MEMBER(NodeMappingInfo,Attribute,at)
00178             >
00179             >
00180             > NodeMapping;
00182         NodeMapping nm;
00183         typedef NodeMapping::index<NodeInfoTag>::type NodeNodeInfoIndex;
00185         std::vector<std::vector<Attribute> > depSCC;
00186 
00187         // some indices
00191         typedef std::pair<std::set<VariableLocation>, boost::unordered_set<Attribute> > SafetyPreconditions;
00192 
00194         boost::unordered_map<Attribute, SafetyPreconditions> safetyPreconditions;
00195 
00197         boost::unordered_map<VariableLocation, boost::unordered_set<Attribute> > attributesSafeByVariable;
00199         boost::unordered_map<Attribute, boost::unordered_set<Attribute> > attributesSafeByAttribute;
00200 
00202         boost::unordered_map<Attribute, std::set<AtomLocation> > attributeOccursIn;
00204         boost::unordered_map<VariableLocation, std::set<AtomLocation> > variableOccursIn;
00205 
00206         // output
00208         boost::unordered_map<ID, int> predicateArity;
00210         std::set<Node> cyclicAttributes;
00212         boost::unordered_set<VariableLocation> boundedVariables;
00214         boost::unordered_set<Attribute> domainExpansionSafeAttributes;
00216         boost::unordered_set<IDAddress> necessaryExternalAtoms;
00218         boost::unordered_set<std::pair<ID, VariableLocation> > boundedByExternals;
00219 
00220     public:
00228         Attribute getAttribute(ID eatomID, ID predicate, std::vector<ID> inputList, ID ruleID, bool inputAttribute, int argumentIndex);
00233         Attribute getAttribute(ID predicate, int argumentIndex);
00234 
00235     private:
00239         Node getNode(Attribute at);
00240 
00241         // helper
00247         bool hasInformationFlow(boost::unordered_map<ID, boost::unordered_set<ID> >& builtinflow, ID from, ID to);
00251         bool isNewlySafe(Attribute at);
00252 
00253     public:
00254         // trigger functions
00256         void addExternallyBoundedVariable(ID extAtom, VariableLocation vl);
00258         void addBoundedVariable(VariableLocation vl);
00260         void addDomainExpansionSafeAttribute(Attribute at);
00261 
00264         const std::vector<ID>& getIdb();
00267         const Graph& getAttributeGraph();
00270         const std::vector<std::vector<Attribute> >& getDepSCC();
00273         const boost::unordered_set<Attribute>& getDomainExpansionSafeAttributes();
00276         const boost::unordered_set<VariableLocation>& getBoundedVariables();
00277         void getReachableAttributes(Attribute start, std::set<Node>& output);
00281         int getPredicateArity(ID predicate) const;
00282 
00283     private:
00284         // initialization
00288         void computeBuiltinInformationFlow(const Rule& rule, boost::unordered_map<ID, boost::unordered_set<ID> >& builtinflow);
00289 
00291         void createDependencyGraph();
00293         void createPreconditionsAndLocationIndices();
00295         void computeCyclicAttributes();
00296 
00297         // computation
00299         void ensureOrdinarySafety();
00300 
00302         void computeDomainExpansionSafety();
00303 
00305         std::vector<LiberalSafetyPluginPtr> safetyPlugins;
00306     public:
00311         LiberalSafetyChecker(RegistryPtr reg, const std::vector<ID>& idb, std::vector<LiberalSafetyPluginFactoryPtr> customSafetyPlugins);
00312 
00315         bool isDomainExpansionSafe() const;
00319         bool isExternalAtomNecessaryForDomainExpansionSafety(ID eatomID) const;
00320 
00324         virtual void writeGraphViz(std::ostream& o, bool verbose) const;
00325 };
00326 
00327 DLVHEX_EXPORT std::size_t hash_value(const LiberalSafetyChecker::Attribute& at);
00328 DLVHEX_EXPORT std::size_t hash_value(const LiberalSafetyChecker::VariableLocation& vl);
00329 
00330 typedef boost::shared_ptr<LiberalSafetyChecker> LiberalSafetyCheckerPtr;
00331 typedef boost::shared_ptr<const LiberalSafetyChecker> LiberalSafetyCheckerConstPtr;
00332 
00333 DLVHEX_NAMESPACE_END
00334 #endif
00335 
00336 // vim:expandtab:ts=4:sw=4:
00337 // mode: C++
00338 // End: