dlvhex  2.5.0
include/dlvhex2/RuleTable.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 
00034 #ifndef RULETABLE_HPP_INCLUDED__12102010
00035 #define RULETABLE_HPP_INCLUDED__12102010
00036 
00037 #include "dlvhex2/PlatformDefinitions.h"
00038 #include "dlvhex2/fwd.h"
00039 #include "dlvhex2/Rule.h"
00040 #include "dlvhex2/Table.h"
00041 
00042 #include <boost/multi_index/hashed_index.hpp>
00043 #include <boost/multi_index/member.hpp>
00044 #include <boost/multi_index/random_access_index.hpp>
00045 #include <boost/multi_index/ordered_index.hpp>
00046 #include <boost/multi_index/composite_key.hpp>
00047 
00048 DLVHEX_NAMESPACE_BEGIN
00049 
00051 class RuleTable:
00052 public Table<
00053 // value type is symbol struct
00054 Rule,
00055 // index is
00056 boost::multi_index::indexed_by<
00057 // address = running ID for constant access
00058 boost::multi_index::random_access<
00059 boost::multi_index::tag<impl::AddressTag>
00060 >,
00061 // kind
00062 boost::multi_index::ordered_non_unique<
00063 boost::multi_index::tag<impl::KindTag>,
00064 BOOST_MULTI_INDEX_MEMBER(Rule,IDKind,kind)
00065 >,
00066 // element
00067 boost::multi_index::hashed_unique<
00068 boost::multi_index::tag<impl::ElementTag>,
00069 boost::multi_index::composite_key<
00070 Rule,
00071 BOOST_MULTI_INDEX_MEMBER(Rule,IDKind,kind),
00072 BOOST_MULTI_INDEX_MEMBER(Rule,Tuple,head),
00073 BOOST_MULTI_INDEX_MEMBER(Rule,Tuple,body),
00074 BOOST_MULTI_INDEX_MEMBER(Rule,Tuple,headGuard),
00075 BOOST_MULTI_INDEX_MEMBER(Rule,Tuple,bodyWeightVector),
00076 BOOST_MULTI_INDEX_MEMBER(Rule,ID,bound),
00077 BOOST_MULTI_INDEX_MEMBER(Rule,ID,weight),
00078 BOOST_MULTI_INDEX_MEMBER(Rule,ID,level),
00079 BOOST_MULTI_INDEX_MEMBER(Rule,Tuple,weakconstraintVector)
00080 >
00081 >
00082 >
00083 >
00084 {
00085     // types
00086     public:
00087         typedef Container::index<impl::AddressTag>::type AddressIndex;
00088         typedef Container::index<impl::KindTag>::type KindIndex;
00089         typedef Container::index<impl::ElementTag>::type ElementIndex;
00090         typedef AddressIndex::iterator AddressIterator;
00091         typedef ElementIndex::iterator ElementIterator;
00092         // methods
00093     public:
00100         inline const Rule& getByID(ID id) const throw ();
00101 
00105         inline ID getIDByElement(const Rule& rule) const throw();
00106 
00113         inline ID storeAndGetID(const Rule& rule) throw();
00115         inline void clear();
00116 
00123         inline void update(
00124             const Rule& oldStorage, Rule& newStorage) throw();
00125 
00133         std::ostream& print(std::ostream& o, RegistryPtr reg) const throw();
00134 
00139         inline std::pair<AddressIterator, AddressIterator>
00140             getAllByAddress() const throw();
00141 };
00142 
00143 // retrieve by ID
00144 // assert that id.kind is correct for Rule
00145 // assert that ID exists
00146 const Rule&
00147 RuleTable::getByID(
00148 ID id) const throw ()
00149 {
00150     assert(id.isRule());
00151     assert(id.isRegularRule() || id.isConstraint() || id.isWeakConstraint() || id.isWeightRule());
00152     ReadLock lock(mutex);
00153     const AddressIndex& idx = container.get<impl::AddressTag>();
00154     // the following check only works for random access indices, but here it is ok
00155     assert( id.address < idx.size() );
00156     return idx.at(id.address);
00157 }
00158 
00159 
00160 // getID by rule
00161 ID RuleTable::getIDByElement(const Rule& rule) const throw()
00162 {
00163     ReadLock lock(mutex);
00164     const ElementIndex& sidx = container.get<impl::ElementTag>();
00165     ElementIndex::const_iterator it = sidx.find( boost::make_tuple(rule.kind, rule.head, rule.body, rule.headGuard, rule.bodyWeightVector, rule.bound, rule.weight, rule.level, rule.weakconstraintVector) );
00166     if( it == sidx.end() )
00167         return ID_FAIL;
00168     else {
00169         const AddressIndex& aidx = container.get<impl::AddressTag>();
00170         return ID(
00171             it->kind,            // kind
00172                                  // address
00173             container.project<impl::AddressTag>(it) - aidx.begin()
00174             );
00175     }
00176 }
00177 
00178 
00179 // store rule
00180 ID RuleTable::storeAndGetID(
00181 const Rule& rule) throw()
00182 {
00183     assert(ID(rule.kind,0).isRule());
00184     assert(ID(rule.kind,0).isRegularRule() ||
00185         ID(rule.kind,0).isConstraint() ||
00186         ID(rule.kind,0).isWeakConstraint() ||
00187         ID(rule.kind,0).isWeightRule());
00188     assert(!(rule.head.empty() && rule.body.empty()));
00189     assert(!(rule.head.empty() && ID(rule.kind,0).isRegularRule()));
00190     assert(!(rule.head.size() > 1 && !ID(rule.kind,0).isRuleDisjunctive()));
00191 
00192     AddressIndex::const_iterator it;
00193     bool success;
00194 
00195     WriteLock lock(mutex);
00196     AddressIndex& idx = container.get<impl::AddressTag>();
00197     boost::tie(it, success) = idx.push_back(rule);
00198     (void)success;
00199     assert(success);
00200 
00201     return ID(
00202         rule.kind,               // kind
00203                                  // address
00204         container.project<impl::AddressTag>(it) - idx.begin()
00205         );
00206 }
00207 
00208 
00209 void RuleTable::clear()
00210 {
00211     WriteLock lock(mutex);
00212     container.clear();
00213 }
00214 
00215 
00216 void RuleTable::update(
00217 const Rule& oldStorage, Rule& newStorage) throw()
00218 {
00219     bool success;
00220 
00221     WriteLock lock(mutex);
00222     AddressIndex& idx = container.get<impl::AddressTag>();
00223     AddressIndex::iterator it(idx.iterator_to(oldStorage));
00224     assert(it != idx.end());
00225     success = idx.replace(it, newStorage);
00226     (void)success;
00227     assert(success);
00228 }
00229 
00230 
00231 // get range over all rules sorted by address
00232 // NOTE: you may need to lock the mutex also while iterating!
00233 std::pair<RuleTable::AddressIterator, RuleTable::AddressIterator>
00234 RuleTable::getAllByAddress() const throw()
00235 {
00236     ReadLock lock(mutex);
00237     const AddressIndex& idx = container.get<impl::AddressTag>();
00238     return std::make_pair(idx.begin(), idx.end());
00239 }
00240 
00241 
00242 DLVHEX_NAMESPACE_END
00243 #endif                           // RULETABLE_HPP_INCLUDED__12102010
00244 
00245 // vim:expandtab:ts=4:sw=4:
00246 // mode: C++
00247 // End: