dlvhex
2.5.0
|
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 00037 #ifndef FIXTURES_EXT1_HPP_INCLUDED__08112010 00038 #define FIXTURES_EXT1_HPP_INCLUDED__08112010 00039 00040 #include "dlvhex2/PlatformDefinitions.h" 00041 #include "dlvhex2/ComponentGraph.h" 00042 #include "dlvhex2/DependencyGraph.h" 00043 #include "dlvhex2/InputProvider.h" 00044 #include "dlvhex2/HexParser.h" 00045 #include "dlvhex2/ProgramCtx.h" 00046 #include "dlvhex2/Registry.h" 00047 #include "dlvhex2/PluginInterface.h" 00048 #include "dlvhex2/ID.h" 00049 #include "dlvhex2/Interpretation.h" 00050 #include "fixturesDepgraphCompgraphGeneric.h" 00051 #include <boost/foreach.hpp> 00052 00053 using dlvhex::ID; 00054 using dlvhex::Tuple; 00055 00056 // 00057 // dummy plugin atoms 00058 // 00059 class TestPluginAtomCount: 00060 public dlvhex::PluginAtom 00061 { 00062 public: 00063 TestPluginAtomCount(): 00064 dlvhex::PluginAtom("count", false) 00065 { 00066 addInputPredicate(); 00067 outputSize = 1; 00068 } 00069 00070 virtual void retrieve(const Query& q, Answer& a) throw (dlvhex::PluginError) 00071 { 00072 LOG_SCOPE(INFO,"TPEAC::r",false); 00073 LOG(INFO,"= TestPluginAtomCount::retrieve"); 00074 00075 // calculate count of matches with single predicate input parameter 00076 // if pattern is variable, return tuple with count 00077 // otherwise: 00078 // if pattern equal to count return empty tuple 00079 // otherwise return no tuple 00080 00081 // calculate count 00082 assert(q.input.size() == 1); 00083 const ID pred = q.input.front(); 00084 LOG(INFO,"input predicate is " << pred); 00085 00086 // we know that we only have one predicate input 00087 // -> count bits in interpretation 00088 assert(q.interpretation != 0); 00089 const dlvhex::Interpretation::Storage& bits = q.interpretation->getStorage(); 00090 unsigned count = bits.count(); 00091 LOG(INFO,"found " << count << " bits in interpretation " << *q.interpretation); 00092 00093 // assert that we only get good bits by iterating through all 00094 // ground atoms matching given predicate 00095 { 00096 // this is tricky :-) 00097 dlvhex::InterpretationPtr controlint(new dlvhex::Interpretation(registry)); 00098 dlvhex::Interpretation::Storage& controlbits = controlint->getStorage(); 00099 controlbits.resize(bits.size()); 00100 dlvhex::OrdinaryAtomTable::PredicateIterator it, it_end; 00101 assert(registry != 0); 00102 for(boost::tie(it, it_end) = registry->ogatoms.getRangeByPredicateID(pred); 00103 it != it_end; ++it) 00104 { 00105 const dlvhex::OrdinaryAtom& oatom = *it; 00106 controlbits.set(registry->ogatoms.getIDByStorage(oatom).address); 00107 } 00108 00109 // now all bits that are possibly be allowed to be on in 00110 // "bits" are on in "controlbits" 00111 unsigned shouldbecount = controlbits.count(); 00112 LOG(INFO,"control interpretation has " << shouldbecount << " bits: " << *controlint); 00113 // so this must not increase the count 00114 controlbits |= bits; 00115 // assert this! 00116 assert(shouldbecount == controlbits.count()); 00117 } 00118 00119 assert(q.pattern.size() == 1); 00120 ID out = q.pattern.front(); 00121 if( (out.isTerm() && out.isVariableTerm()) || 00122 (out.isTerm() && out.isIntegerTerm() && out.address == count) ) 00123 { 00124 Tuple t; 00125 t.push_back(ID::termFromInteger(count)); 00126 a.get().push_back(t); 00127 } 00128 } 00129 }; 00130 00131 class TestPluginAtomReach: 00132 public dlvhex::PluginAtom 00133 { 00134 public: 00135 TestPluginAtomReach(): 00136 dlvhex::PluginAtom("reach", true) 00137 { 00138 addInputConstant(); 00139 addInputPredicate(); 00140 outputSize = 1; 00141 } 00142 00143 virtual void retrieve(const Query& q, Answer& a) throw (dlvhex::PluginError) 00144 { 00145 // we fake this and do not make transitive closure! 00146 00147 // given constant input C and predicate input P, 00148 // get list of atoms matching P(C,X) 00149 // where X is anything if pattern contains a variable 00150 // where X is equal to the term in the pattern if pattern does not contain a variable 00151 // 00152 // if pattern is variable, return tuple for each X with X 00153 // otherwise 00154 // if pattern equal to one X return empty tuple 00155 // otherwise return no tuple 00156 00157 // get inputs 00158 assert(q.input.size() == 2); 00159 ID start = q.input[0]; 00160 ID pred = q.input[1]; 00161 LOG(INFO,"calculating reach fake extatom for start " << start << " and predicate " << pred); 00162 00163 // build set of found targets 00164 std::set<ID> targets; 00165 assert(q.interpretation != 0); 00166 dlvhex::OrdinaryAtomTable::PredicateIterator it, it_end; 00167 assert(registry != 0); 00168 for(boost::tie(it, it_end) = registry->ogatoms.getRangeByPredicateID(pred); 00169 it != it_end; ++it) 00170 { 00171 const dlvhex::OrdinaryAtom& oatom = *it; 00172 00173 // skip ogatoms not present in interpretation 00174 if( !q.interpretation->getFact(registry->ogatoms.getIDByStorage(oatom).address) ) 00175 continue; 00176 00177 // the edge predicate must be binary 00178 assert(oatom.tuple.size() == 3); 00179 if( oatom.tuple[1] == start ) 00180 targets.insert(oatom.tuple[2]); 00181 } 00182 LOG(INFO,"found targets " << printrange(targets)); 00183 00184 assert(q.pattern.size() == 1); 00185 ID out = q.pattern.front(); 00186 if( out.isTerm() && out.isVariableTerm() ) 00187 { 00188 BOOST_FOREACH(ID id, targets) 00189 { 00190 Tuple t; 00191 t.push_back(id); 00192 a.get().push_back(t); 00193 } 00194 } 00195 else 00196 { 00197 if( targets.find(out) != targets.end() ) 00198 { 00199 Tuple t; 00200 t.push_back(out); 00201 a.get().push_back(t); 00202 } 00203 } 00204 } 00205 }; 00206 00207 // provide program 00208 // parse into ProgramCtx 00209 // register dummy atoms 00210 struct ProgramExt1ProgramCtxFixture 00211 { 00212 std::string program; 00213 dlvhex::ProgramCtx ctx; 00214 dlvhex::PluginAtomPtr papCount; 00215 dlvhex::PluginAtomPtr papReach; 00216 00217 ProgramExt1ProgramCtxFixture(); 00218 ~ProgramExt1ProgramCtxFixture() {} 00219 }; 00220 00221 typedef GenericDepGraphFixture<ProgramExt1ProgramCtxFixture> 00222 ProgramExt1ProgramCtxDependencyGraphFixture; 00223 typedef GenericDepGraphCompGraphFixture<ProgramExt1ProgramCtxFixture> 00224 ProgramExt1ProgramCtxDependencyGraphComponentGraphFixture; 00225 00226 // 00227 // implementation 00228 // 00229 00230 ProgramExt1ProgramCtxFixture::ProgramExt1ProgramCtxFixture(): 00231 papCount(new TestPluginAtomCount), 00232 papReach(new TestPluginAtomReach) 00233 { 00234 using namespace dlvhex; 00235 ctx.setupRegistry(RegistryPtr(new Registry)); 00236 00237 ctx.addPluginAtom(papCount); 00238 ctx.addPluginAtom(papReach); 00239 00240 std::stringstream ss; 00241 ss << 00242 "part(leg). item(table)." << std::endl << 00243 "startnode(vienna). edge(vienna,london)." << std::endl << 00244 "item(X) :- part(X)." << std::endl << 00245 "edge(Y,Y) :- foo(Y)." << std::endl << 00246 "num(N) :- &count[item](N)." << std::endl << 00247 "reached(X) :- &reach[N,edge](X), startnode(N)." << std::endl; 00248 InputProviderPtr ip(new InputProvider); 00249 ip->addStreamInput(ss, "testcase"); 00250 ModuleHexParser parser; 00251 parser.parse(ip, ctx); 00252 00253 ctx.associateExtAtomsWithPluginAtoms(ctx.idb, true); 00254 } 00255 00256 #endif // FIXTURES_EXT1_HPP_INCLUDED__08112010