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 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