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 00034 #ifndef ORDINARYATOMTABLE_HPP_INCLUDED__12102010 00035 #define ORDINARYATOMTABLE_HPP_INCLUDED__12102010 00036 00037 #include "dlvhex2/PlatformDefinitions.h" 00038 #include "dlvhex2/Atoms.h" 00039 #include "dlvhex2/Table.h" 00040 00041 #include <boost/multi_index/member.hpp> 00042 #include <boost/multi_index/mem_fun.hpp> 00043 #include <boost/multi_index/hashed_index.hpp> 00044 #include <boost/multi_index/random_access_index.hpp> 00045 00046 DLVHEX_NAMESPACE_BEGIN 00047 00049 class OrdinaryAtomTable: 00050 public Table< 00051 // value type is symbol struct 00052 OrdinaryAtom, 00053 // index is 00054 boost::multi_index::indexed_by< 00055 // address = running ID for constant access 00056 boost::multi_index::random_access< 00057 boost::multi_index::tag<impl::AddressTag> 00058 >, 00059 // (unique) textual representation (parsing index, see TODO above) 00060 boost::multi_index::hashed_unique< 00061 boost::multi_index::tag<impl::TextTag>, 00062 BOOST_MULTI_INDEX_MEMBER(OrdinaryAtom,std::string,text) 00063 >, 00064 // unique IDs for unique tuples 00065 boost::multi_index::hashed_unique< 00066 boost::multi_index::tag<impl::TupleTag>, 00067 BOOST_MULTI_INDEX_MEMBER(OrdinaryAtom::Atom,Tuple,tuple) 00068 >, 00069 boost::multi_index::hashed_non_unique< 00070 boost::multi_index::tag<impl::PredicateTag>, 00071 // we cannot use BOOST_MULTI_INDEX_CONST_MEM_FUN here, it required MemberFunName to be in Class 00072 //BOOST_MULTI_INDEX_CONST_MEM_FUN(OrdinaryAtom,ID,front) 00073 boost::multi_index::const_mem_fun_explicit<OrdinaryAtom,ID, 00074 ID (Atom::*)() const,&Atom::front> 00075 > 00076 > 00077 > 00078 { 00079 // types 00080 public: 00081 typedef Container::index<impl::AddressTag>::type AddressIndex; 00082 //typedef Container::index<impl::KindTag>::type KindIndex; 00083 typedef Container::index<impl::TextTag>::type TextIndex; 00084 typedef Container::index<impl::TupleTag>::type TupleIndex; 00085 typedef Container::index<impl::PredicateTag>::type PredicateIndex; 00086 typedef AddressIndex::iterator AddressIterator; 00087 typedef PredicateIndex::iterator PredicateIterator; 00088 00089 // methods 00090 public: 00098 inline const OrdinaryAtom& getByID(ID id) const throw (); 00099 00106 inline const OrdinaryAtom& getByAddress(IDAddress addr) const throw (); 00107 00114 inline ID getIDByAddress(IDAddress addr) const throw (); 00115 00119 inline ID getIDByString(const std::string& text) const throw(); 00120 00125 inline ID getIDByTuple(const Tuple& tuple) const throw(); 00126 00132 inline ID getIDByStorage(const OrdinaryAtom& atom) const throw (); 00133 00139 inline IDAddress getIDAddressByStorage(const OrdinaryAtom& atom) const throw (); 00140 00146 inline ID storeAndGetID(const OrdinaryAtom& atom) throw(); 00147 00154 inline std::pair<PredicateIterator, PredicateIterator> 00155 getRangeByPredicateID(ID id) const throw(); 00156 00162 inline std::pair<AddressIterator, AddressIterator> 00163 getAllByAddress() const throw(); 00164 }; 00165 00166 // retrieve by ID 00167 // assert that id.kind is correct for Term 00168 // assert that ID exists 00169 const OrdinaryAtom& 00170 OrdinaryAtomTable::getByID( 00171 ID id) const throw () 00172 { 00173 assert(id.isAtom() || id.isLiteral()); 00174 assert(id.isOrdinaryAtom()); 00175 ReadLock lock(mutex); 00176 const AddressIndex& idx = container.get<impl::AddressTag>(); 00177 // the following check only works for random access indices, but here it is ok 00178 assert( id.address < idx.size() ); 00179 return idx.at(id.address); 00180 } 00181 00182 00183 // retrieve by address (ignore kind) 00184 // assert that address exists in table 00185 const OrdinaryAtom& 00186 OrdinaryAtomTable::getByAddress( 00187 IDAddress addr) const throw () 00188 { 00189 ReadLock lock(mutex); 00190 const AddressIndex& idx(container.get<impl::AddressTag>()); 00191 // the following check only works for random access indices, but here it is ok 00192 assert( addr < idx.size() ); 00193 return idx.at(addr); 00194 } 00195 00196 00197 // retrieve ID by address 00198 // assert that address exists in table 00199 ID 00200 OrdinaryAtomTable::getIDByAddress( 00201 IDAddress addr) const throw () 00202 { 00203 const OrdinaryAtom& atom = getByAddress(addr); 00204 return ID(atom.kind, addr); 00205 } 00206 00207 00208 // given string, look if already stored 00209 // if no, return ID_FAIL, otherwise return ID 00210 ID OrdinaryAtomTable::getIDByString( 00211 const std::string& str) const throw() 00212 { 00213 typedef Container::index<impl::TextTag>::type OrdinaryAtomIndex; 00214 ReadLock lock(mutex); 00215 const TextIndex& sidx(container.get<impl::TextTag>()); 00216 TextIndex::const_iterator it(sidx.find(str)); 00217 if( it == sidx.end() ) 00218 return ID_FAIL; 00219 else { 00220 const AddressIndex& aidx(container.get<impl::AddressTag>()); 00221 return ID( 00222 it->kind, // kind 00223 // address 00224 container.project<impl::AddressTag>(it) - aidx.begin() 00225 ); 00226 } 00227 } 00228 00229 00230 // given tuple, look if already stored 00231 // if no, return ID_FAIL, otherwise return ID 00232 ID OrdinaryAtomTable::getIDByTuple( 00233 const Tuple& tuple) const throw() 00234 { 00235 typedef Container::index<impl::TupleTag>::type TupleIndex; 00236 ReadLock lock(mutex); 00237 const TupleIndex& sidx(container.get<impl::TupleTag>()); 00238 TupleIndex::const_iterator it(sidx.find(tuple)); 00239 if( it == sidx.end() ) 00240 return ID_FAIL; 00241 else { 00242 const AddressIndex& aidx(container.get<impl::AddressTag>()); 00243 return ID( 00244 it->kind, // kind 00245 // address 00246 container.project<impl::AddressTag>(it) - aidx.begin() 00247 ); 00248 } 00249 } 00250 00251 00252 // get ID given storage retrieved by other means 00253 // (storage must have originated from iterator from here) 00254 ID OrdinaryAtomTable::getIDByStorage( 00255 const OrdinaryAtom& atom) const throw () 00256 { 00257 // we cannot assert anything really useful here! 00258 // (if the user specifies another storage, iterator_to will segfault 00259 // anyway as there is no associated internal multi_index storage node) 00260 ReadLock lock(mutex); 00261 const AddressIndex& aidx(container.get<impl::AddressTag>()); 00262 AddressIndex::const_iterator it(aidx.iterator_to(atom)); 00263 assert(atom.kind == it->kind); 00264 return ID( 00265 atom.kind, // kind 00266 it - aidx.begin() // address 00267 ); 00268 } 00269 00270 00271 // get IDAddress of given storage retrieved by other means 00272 // (storage must have originated from iterator from here) 00273 IDAddress OrdinaryAtomTable::getIDAddressByStorage( 00274 const OrdinaryAtom& atom) const throw () 00275 { 00276 // we cannot assert anything really useful here! 00277 // (if the user specifies another storage, iterator_to will segfault 00278 // anyway as there is no associated internal multi_index storage node) 00279 ReadLock lock(mutex); 00280 const AddressIndex& aidx(container.get<impl::AddressTag>()); 00281 AddressIndex::const_iterator it(aidx.iterator_to(atom)); 00282 assert(atom.kind == it->kind); 00283 return it - aidx.begin(); 00284 } 00285 00286 00287 // store symbol, assuming it does not exist (this is only asserted) 00288 ID OrdinaryAtomTable::storeAndGetID( 00289 const OrdinaryAtom& atm) throw() 00290 { 00291 assert(ID(atm.kind,0).isAtom()); 00292 assert(ID(atm.kind,0).isOrdinaryAtom()); 00293 assert(!atm.text.empty()); 00294 assert(!( 00295 (atm.tuple.front().kind & ID::PROPERTY_AUX) != 0 && 00296 (atm.kind & ID::PROPERTY_AUX) == 0 ) && 00297 "atom must be auxiliary if predicate term is auxiliary"); 00298 00299 AddressIndex::const_iterator it; 00300 bool success; 00301 00302 WriteLock lock(mutex); 00303 AddressIndex& idx(container.get<impl::AddressTag>()); 00304 boost::tie(it, success) = idx.push_back(atm); 00305 (void)success; 00306 assert(success); 00307 00308 return ID( 00309 atm.kind, // kind 00310 // address 00311 container.project<impl::AddressTag>(it) - idx.begin() 00312 ); 00313 } 00314 00315 00316 // get all ordinary atoms with certain predicate id 00317 // NOTE: you may need to lock the mutex also while iterating! 00318 // if you intend to use this method frequently, consider to use a PredicateMask instead for better efficiency (iteration is slow) 00319 std::pair<OrdinaryAtomTable::PredicateIterator, OrdinaryAtomTable::PredicateIterator> 00320 OrdinaryAtomTable::getRangeByPredicateID(ID id) const throw() 00321 { 00322 assert(id.isTerm()); 00323 ReadLock lock(mutex); 00324 const PredicateIndex& idx = container.get<impl::PredicateTag>(); 00325 return idx.equal_range(id); 00326 } 00327 00328 00329 // get range over all atoms sorted by address 00330 // NOTE: you may need to lock the mutex also while iterating! 00331 std::pair<OrdinaryAtomTable::AddressIterator, OrdinaryAtomTable::AddressIterator> 00332 OrdinaryAtomTable::getAllByAddress() const throw() 00333 { 00334 ReadLock lock(mutex); 00335 const AddressIndex& idx = container.get<impl::AddressTag>(); 00336 return std::make_pair(idx.begin(), idx.end()); 00337 } 00338 00339 00340 DLVHEX_NAMESPACE_END 00341 #endif // ORDINARYATOMTABLE_HPP_INCLUDED__12102010 00342 00343 // vim:expandtab:ts=4:sw=4: 00344 // mode: C++ 00345 // End: