dlvhex  2.5.0
testsuite/fixturesExt1.h
Go to the documentation of this file.
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