dlvhex  2.5.0
testsuite/TestDependencyGraph.cpp
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 
00031 #ifdef HAVE_CONFIG_H
00032 #include "config.h"
00033 #endif // HAVE_CONFIG_H
00034 
00035 #include <boost/cstdint.hpp>
00036 #include "dlvhex2/DependencyGraph.h"
00037 //#include "dlvhex2/DependencyGraphFull.h"
00038 #include "dlvhex2/HexParser.h"
00039 #include "dlvhex2/InputProvider.h"
00040 #include "dlvhex2/ProgramCtx.h"
00041 #include "dlvhex2/Printer.h"
00042 #include "dlvhex2/Registry.h"
00043 #include "dlvhex2/PluginInterface.h"
00044 #include "dlvhex2/Interpretation.h"
00045 
00046 #define BOOST_TEST_MODULE "TestDependencyGraph"
00047 #include <boost/test/unit_test.hpp>
00048 
00049 #include "fixturesExt1.h"
00050 #include "fixturesMCS.h"
00051 #include "graphviz.h"
00052 
00053 #include <iostream>
00054 #include <fstream>
00055 
00056 #define LOG_REGISTRY_PROGRAM(ctx) \
00057   LOG(INFO,*ctx.registry()); \
00058     RawPrinter printer(std::cerr, ctx.registry()); \
00059     std::cerr << "edb = " << *ctx.edb << std::endl; \
00060     LOG(INFO,"idb"); \
00061     printer.printmany(ctx.idb,"\n"); \
00062     std::cerr << std::endl; \
00063     LOG(INFO,"idb end");
00064 
00065 LOG_INIT(Logger::ERROR | Logger::WARNING)
00066 
00067 DLVHEX_NAMESPACE_USE
00068 
00069 BOOST_AUTO_TEST_CASE(testDisj) 
00070 {
00071   ProgramCtx ctx;
00072   ctx.setupRegistry(RegistryPtr(new Registry));
00073 
00074   std::stringstream ss;
00075   ss <<
00076         // a <-(+)-> a (head/head = disjunctive)
00077     "a v b." << std::endl <<
00078     "a v c." << std::endl;
00079   InputProviderPtr ip(new InputProvider);
00080   ip->addStreamInput(ss, "testinput");
00081   ModuleHexParser parser;
00082   BOOST_REQUIRE_NO_THROW(parser.parse(ip, ctx));
00083 
00084     LOG_REGISTRY_PROGRAM(ctx);
00085 
00086   ID ida = ctx.registry()->ogatoms.getIDByString("a");
00087   ID idb = ctx.registry()->ogatoms.getIDByString("b");
00088   ID idc = ctx.registry()->ogatoms.getIDByString("c");
00089   BOOST_REQUIRE((ida | idb | idc) != ID_FAIL);
00090 
00091   // smaller more efficient dependency graph
00092   {
00093     DependencyGraph depgraph(ctx, ctx.registry());
00094     std::vector<ID> auxRules;
00095     depgraph.createDependencies(ctx.idb, auxRules);
00096 
00097     BOOST_CHECK_EQUAL(depgraph.countNodes(), 2);
00098     BOOST_CHECK_EQUAL(depgraph.countDependencies(), 2);
00099 
00100     // TODO test dependencies (will do manually with graphviz at the moment)
00101 
00102     const char* fnamev = "testDependencyGraphDisjVerbose.dot";
00103     LOG(INFO,"dumping verbose graph to " << fnamev);
00104     std::ofstream filev(fnamev);
00105     depgraph.writeGraphViz(filev, true);
00106     makeGraphVizPdf(fnamev);
00107 
00108     const char* fnamet = "testDependencyGraphDisjTerse.dot";
00109     LOG(INFO,"dumping terse graph to " << fnamet);
00110     std::ofstream filet(fnamet);
00111     depgraph.writeGraphViz(filet, false);
00112     makeGraphVizPdf(fnamet);
00113   }
00114 }
00115 
00116 BOOST_AUTO_TEST_CASE(testNonext) 
00117 {
00118   ProgramCtx ctx;
00119   ctx.setupRegistry(RegistryPtr(new Registry));
00120 
00121   std::stringstream ss;
00122   ss <<
00123         // a <-(+)-> f(X) (head/head = disjunctive)
00124     // 2x head -> rule
00125     "a v f(X)." << std::endl <<
00126       // f(a) -(+)-> f(X) (unifying+?)
00127       // f(b) -(+)-> f(X) (unifying+?)
00128       // b -> rule (head/rule = positive)
00129     // rule -(+)-> f(a) (rule/body = positive)
00130       // rule -(-)-> f(b) (rule/nafbody = negative)
00131     "b :- f(a), not f(b)." << std::endl <<
00132       // f(b) -(+c)-> f(X) (unifying pos_constraint)
00133       // f(a) -(-c)-> f(X) (unifying neg_constraint)
00134     // rule -> body (pos_constraint)
00135     // rule -> nafbody (neg_constraint)
00136     ":- f(b), not f(a)." << std::endl;
00137   InputProviderPtr ip(new InputProvider);
00138   ip->addStreamInput(ss, "testinput");
00139   ModuleHexParser parser;
00140   BOOST_REQUIRE_NO_THROW(parser.parse(ip, ctx));
00141 
00142     LOG_REGISTRY_PROGRAM(ctx);
00143 
00144   ID ida = ctx.registry()->ogatoms.getIDByString("a");
00145   ID idb = ctx.registry()->ogatoms.getIDByString("b");
00146   ID idfb = ctx.registry()->ogatoms.getIDByString("f(b)");
00147   ID idfa = ctx.registry()->ogatoms.getIDByString("f(a)");
00148   BOOST_REQUIRE((ida | idb | idfb | idfa) != ID_FAIL);
00149 
00150   ID idfX = ctx.registry()->onatoms.getIDByString("f(X)");
00151   BOOST_REQUIRE(idfX != ID_FAIL);
00152 
00153 /*
00154   // full dependency graph
00155   {
00156     DependencyGraphFull depgraph(ctx.registry());
00157     depgraph.createNodesAndBasicDependencies(ctx.idb);
00158     depgraph.createUnifyingDependencies();
00159 
00160     BOOST_CHECK_EQUAL(depgraph.countNodes(), 8);
00161     BOOST_CHECK_EQUAL(depgraph.countDependencies(), 11);
00162 
00163     const char* fnamev = "testDependencyGraphNonextFullVerbose.dot";
00164     LOG(INFO,"dumping verbose graph to " << fnamev);
00165     std::ofstream filev(fnamev);
00166     depgraph.writeGraphViz(filev, true);
00167     makeGraphVizPdf(fnamev);
00168 
00169     const char* fnamet = "testDependencyGraphNonextFullTerse.dot";
00170     LOG(INFO,"dumping terse graph to " << fnamet);
00171     std::ofstream filet(fnamet);
00172     depgraph.writeGraphViz(filet, false);
00173     makeGraphVizPdf(fnamet);
00174   }
00175 */
00176 
00177   // smaller more efficient dependency graph
00178   {
00179     DependencyGraph depgraph(ctx, ctx.registry());
00180     std::vector<ID> auxRules;
00181     depgraph.createDependencies(ctx.idb, auxRules);
00182 
00183     // TODO
00184     //BOOST_CHECK_EQUAL(depgraph.countNodes(), 10);
00185     //BOOST_CHECK_EQUAL(depgraph.countDependencies(), 13);
00186 
00187     // TODO test dependencies (will do manually with graphviz at the moment)
00188 
00189     const char* fnamev = "testDependencyGraphNonextVerbose.dot";
00190     LOG(INFO,"dumping verbose graph to " << fnamev);
00191     std::ofstream filev(fnamev);
00192     depgraph.writeGraphViz(filev, true);
00193     makeGraphVizPdf(fnamev);
00194 
00195     const char* fnamet = "testDependencyGraphNonextTerse.dot";
00196     LOG(INFO,"dumping terse graph to " << fnamet);
00197     std::ofstream filet(fnamet);
00198     depgraph.writeGraphViz(filet, false);
00199     makeGraphVizPdf(fnamet);
00200   }
00201 }
00202 
00203 BOOST_FIXTURE_TEST_CASE(testExtCountReach,ProgramExt1ProgramCtxFixture) 
00204 {
00205     LOG_REGISTRY_PROGRAM(ctx);
00206 
00207 /*
00208   // full dependency graph
00209   {
00210     // clone registry, because full depgraph will modify it for auxiliary rules
00211     RegistryPtr cloneRegistry(new Registry(*ctx.registry()));
00212     DependencyGraphFull depgraph(cloneRegistry);
00213     depgraph.createNodesAndBasicDependencies(ctx.idb);
00214     depgraph.createUnifyingDependencies();
00215     std::vector<ID> auxRules;
00216     depgraph.createExternalDependencies(auxRules);
00217 
00218     BOOST_CHECK_EQUAL(auxRules.size(), 1);
00219     BOOST_CHECK_EQUAL(depgraph.countNodes(), 13+2); // 1 aux rule + 1 aux predicate
00220     BOOST_CHECK_EQUAL(depgraph.countDependencies(), 12+3); // 3 aux dependencies
00221 
00222     const char* fnamev = "testDependencyGraphExtCountReachFullVerbose.dot";
00223     LOG(INFO,"dumping verbose graph to " << fnamev);
00224     std::ofstream filev(fnamev);
00225     depgraph.writeGraphViz(filev, true);
00226     makeGraphVizPdf(fnamev);
00227 
00228     const char* fnamet = "testDependencyGraphExtCountReachFullTerse.dot";
00229     LOG(INFO,"dumping terse graph to " << fnamet);
00230     std::ofstream filet(fnamet);
00231     depgraph.writeGraphViz(filet, false);
00232     makeGraphVizPdf(fnamet);
00233   }
00234 */
00235 
00236   // smaller more efficient dependency graph
00237   {
00238     DependencyGraph depgraph(ctx, ctx.registry());
00239     std::vector<ID> auxRules;
00240     depgraph.createDependencies(ctx.idb, auxRules);
00241 
00242     // TODO
00243     //BOOST_CHECK_EQUAL(depgraph.countNodes(), 10);
00244     //BOOST_CHECK_EQUAL(depgraph.countDependencies(), 13);
00245 
00246     // TODO test dependencies (will do manually with graphviz at the moment)
00247 
00248     const char* fnamev = "testDependencyGraphExtCountReachVerbose.dot";
00249     LOG(INFO,"dumping verbose graph to " << fnamev);
00250     std::ofstream filev(fnamev);
00251     depgraph.writeGraphViz(filev, true);
00252     makeGraphVizPdf(fnamev);
00253 
00254     const char* fnamet = "testDependencyGraphExtCountReachTerse.dot";
00255     LOG(INFO,"dumping terse graph to " << fnamet);
00256     std::ofstream filet(fnamet);
00257     depgraph.writeGraphViz(filet, false);
00258     makeGraphVizPdf(fnamet);
00259   }
00260 }
00261 
00262 // example using MCS-IE encoding from KR 2010 for calculation of equilibria in medical example
00263 BOOST_FIXTURE_TEST_CASE(testMCSMedEQ,ProgramMCSMedEQProgramCtxFixture) 
00264 {
00265     //LOG_REGISTRY_PROGRAM(ctx);
00266 
00267 /*
00268     // full dependency graph
00269   {
00270     // clone registry, because full depgraph will modify it for auxiliary rules
00271     RegistryPtr cloneRegistry(new Registry(*ctx.registry()));
00272     DependencyGraphFull depgraph(cloneRegistry);
00273     depgraph.createNodesAndBasicDependencies(ctx.idb);
00274     depgraph.createUnifyingDependencies();
00275     std::vector<ID> auxRules;
00276     depgraph.createExternalDependencies(auxRules);
00277 
00278     const char* fnamev = "testDependencyGraphMCSMedEqFullVerbose.dot";
00279     LOG(INFO,"dumping verbose graph to " << fnamev);
00280     std::ofstream filev(fnamev);
00281     depgraph.writeGraphViz(filev, true);
00282     makeGraphVizPdf(fnamev);
00283 
00284     const char* fnamet = "testDependencyGraphMCSMedEqFullTerse.dot";
00285     LOG(INFO,"dumping terse graph to " << fnamet);
00286     std::ofstream filet(fnamet);
00287     depgraph.writeGraphViz(filet, false);
00288     makeGraphVizPdf(fnamet);
00289   }
00290 */
00291 
00292   // smaller more efficient dependency graph
00293   {
00294     DependencyGraph depgraph(ctx, ctx.registry());
00295     std::vector<ID> auxRules;
00296     depgraph.createDependencies(ctx.idb, auxRules);
00297 
00298     // TODO
00299     //BOOST_CHECK_EQUAL(depgraph.countNodes(), 10);
00300     //BOOST_CHECK_EQUAL(depgraph.countDependencies(), 13);
00301 
00302     // TODO test dependencies (will do manually with graphviz at the moment)
00303 
00304     const char* fnamev = "testDependencyGraphMCSMedEqVerbose.dot";
00305     LOG(INFO,"dumping verbose graph to " << fnamev);
00306     std::ofstream filev(fnamev);
00307     depgraph.writeGraphViz(filev, true);
00308     makeGraphVizPdf(fnamev);
00309 
00310     const char* fnamet = "testDependencyGraphMCSMedEqTerse.dot";
00311     LOG(INFO,"dumping terse graph to " << fnamet);
00312     std::ofstream filet(fnamet);
00313     depgraph.writeGraphViz(filet, false);
00314     makeGraphVizPdf(fnamet);
00315   }
00316 }
00317 
00318 // TODO test aggregate dependencies