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