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/HexParser.h" 00037 #include "dlvhex2/InputProvider.h" 00038 #include "dlvhex2/ProgramCtx.h" 00039 #include "dlvhex2/Printer.h" 00040 #include "dlvhex2/Registry.h" 00041 #include "dlvhex2/Interpretation.h" 00042 00043 #define BOOST_TEST_MODULE "TestHexParser" 00044 #include <boost/test/unit_test.hpp> 00045 00046 #include <iostream> 00047 #include <fstream> 00048 00049 #define LOG_REGISTRY_PROGRAM(ctx) \ 00050 LOG(INFO,*ctx.registry()); \ 00051 RawPrinter printer(std::cerr, ctx.registry()); \ 00052 std::cerr << "edb = " << *ctx.edb << std::endl; \ 00053 LOG(INFO,"idb"); \ 00054 printer.printmany(ctx.idb,"\n"); \ 00055 std::cerr << std::endl; \ 00056 LOG(INFO,"idb end"); 00057 00058 LOG_INIT(Logger::ERROR | Logger::WARNING) 00059 00060 DLVHEX_NAMESPACE_USE 00061 00062 BOOST_AUTO_TEST_CASE(testHexParserSimple) 00063 { 00064 ProgramCtx ctx; 00065 ctx.setupRegistry(RegistryPtr(new Registry)); 00066 00067 std::stringstream ss; 00068 ss << 00069 "a. b. c(d,e)." << std::endl << 00070 "f(X) v b :- g(X), not h(X,X)." << std::endl; 00071 00072 InputProviderPtr ip(new InputProvider); 00073 ip->addStreamInput(ss, "testinput"); 00074 ModuleHexParser parser; 00075 BOOST_REQUIRE_NO_THROW(parser.parse(ip, ctx)); 00076 00077 LOG_REGISTRY_PROGRAM(ctx); 00078 00079 ID ida = ctx.registry()->ogatoms.getIDByString("a"); 00080 ID idb = ctx.registry()->ogatoms.getIDByString("b"); 00081 ID idcde = ctx.registry()->ogatoms.getIDByString("c(d,e)"); 00082 BOOST_REQUIRE((ida | idb | idcde) != ID_FAIL); 00083 00084 ID idfX = ctx.registry()->onatoms.getIDByString("f(X)"); 00085 ID idgX = ctx.registry()->onatoms.getIDByString("g(X)"); 00086 ID idhXX = ctx.registry()->onatoms.getIDByString("h(X,X)"); 00087 BOOST_REQUIRE((idfX | idgX | idhXX) != ID_FAIL); 00088 00089 BOOST_REQUIRE(ctx.edb != 0); 00090 BOOST_CHECK(ctx.edb->getFact(ida.address)); 00091 BOOST_CHECK(ctx.edb->getFact(idb.address)); 00092 BOOST_CHECK(ctx.edb->getFact(idcde.address)); 00093 00094 BOOST_REQUIRE(ctx.idb.size() == 1); 00095 { 00096 const Rule& r = ctx.registry()->rules.getByID(ctx.idb[0]); 00097 BOOST_CHECK(r.kind == (ID::MAINKIND_RULE | ID::SUBKIND_RULE_REGULAR | ID::PROPERTY_RULE_DISJ )); 00098 BOOST_CHECK(r.weight == ID_FAIL); 00099 BOOST_CHECK(r.level == ID_FAIL); 00100 BOOST_REQUIRE(r.head.size() == 2); 00101 { 00102 BOOST_CHECK(r.head[0] == idfX); 00103 BOOST_CHECK(r.head[1] == idb); 00104 } 00105 BOOST_REQUIRE(r.body.size() == 2); 00106 { 00107 BOOST_CHECK(r.body[0] == ID::posLiteralFromAtom(idgX)); 00108 BOOST_CHECK(r.body[1] == ID::nafLiteralFromAtom(idhXX)); 00109 } 00110 } 00111 } 00112 00113 00114 BOOST_AUTO_TEST_CASE(testHexParserConstraint) 00115 { 00116 ProgramCtx ctx; 00117 ctx.setupRegistry(RegistryPtr(new Registry)); 00118 00119 std::stringstream ss; 00120 ss << 00121 ":- g(X), not h(X,X)." << std::endl; 00122 InputProviderPtr ip(new InputProvider); 00123 ip->addStreamInput(ss, "testinput"); 00124 ModuleHexParser parser; 00125 BOOST_REQUIRE_NO_THROW(parser.parse(ip, ctx)); 00126 00127 LOG_REGISTRY_PROGRAM(ctx); 00128 00129 ID idgX = ctx.registry()->onatoms.getIDByString("g(X)"); 00130 ID idhXX = ctx.registry()->onatoms.getIDByString("h(X,X)"); 00131 BOOST_REQUIRE((idgX | idhXX) != ID_FAIL); 00132 00133 BOOST_REQUIRE(ctx.idb.size() == 1); 00134 { 00135 const Rule& r = ctx.registry()->rules.getByID(ctx.idb[0]); 00136 BOOST_CHECK(r.kind == (ID::MAINKIND_RULE | ID::SUBKIND_RULE_CONSTRAINT)); 00137 BOOST_CHECK(r.weight == ID_FAIL); 00138 BOOST_CHECK(r.level == ID_FAIL); 00139 BOOST_CHECK(r.head.size() == 0); 00140 BOOST_REQUIRE(r.body.size() == 2); 00141 { 00142 BOOST_CHECK(r.body[0] == ID::posLiteralFromAtom(idgX)); 00143 BOOST_CHECK(r.body[1] == ID::nafLiteralFromAtom(idhXX)); 00144 } 00145 } 00146 } 00147 00148 #warning Weak constraints currently not implemented, here is a testcase for them 00149 #if 0 00150 BOOST_AUTO_TEST_CASE(testHexParserWeakConstraint) 00151 { 00152 ProgramCtx ctx; 00153 ctx.setupRegistry(RegistryPtr(new Registry)); 00154 00155 std::stringstream ss; 00156 ss << 00157 ":~ g(X), not h(X,X)." << std::endl << 00158 ":~ g(X). [X:4]"; 00159 InputProviderPtr ip(new InputProvider); 00160 ip->addStreamInput(ss, "testinput"); 00161 ModuleHexParser parser; 00162 BOOST_REQUIRE_NO_THROW(parser.parse(ip, ctx)); 00163 00164 LOG_REGISTRY_PROGRAM(ctx); 00165 00166 ID idX = ctx.registry()->terms.getIDByString("X"); 00167 ID id1 = ID::termFromInteger(1); 00168 ID id4 = ID::termFromInteger(4); 00169 ID idgX = ctx.registry()->onatoms.getIDByString("g(X)"); 00170 ID idhXX = ctx.registry()->onatoms.getIDByString("h(X,X)"); 00171 BOOST_REQUIRE((idX | id1 | id4 | idgX | idhXX) != ID_FAIL); 00172 00173 BOOST_REQUIRE(ctx.idb.size() == 2); 00174 { 00175 const Rule& r = ctx.registry()->rules.getByID(ctx.idb[0]); 00176 BOOST_CHECK(r.kind == (ID::MAINKIND_RULE | ID::SUBKIND_RULE_WEAKCONSTRAINT)); 00177 BOOST_CHECK(r.weight == id1); 00178 BOOST_CHECK(r.level == id1); 00179 BOOST_CHECK(r.head.size() == 0); 00180 BOOST_REQUIRE(r.body.size() == 2); 00181 { 00182 BOOST_CHECK(r.body[0] == ID::posLiteralFromAtom(idgX)); 00183 BOOST_CHECK(r.body[1] == ID::nafLiteralFromAtom(idhXX)); 00184 } 00185 } 00186 { 00187 const Rule& r = ctx.registry()->rules.getByID(ctx.idb[1]); 00188 BOOST_CHECK(r.kind == (ID::MAINKIND_RULE | ID::SUBKIND_RULE_WEAKCONSTRAINT)); 00189 BOOST_CHECK(r.weight == idX); 00190 BOOST_CHECK(r.level == id4); 00191 BOOST_CHECK(r.head.size() == 0); 00192 BOOST_REQUIRE(r.body.size() == 1); 00193 { 00194 BOOST_CHECK(r.body[0] == ID::posLiteralFromAtom(idgX)); 00195 } 00196 } 00197 } 00198 #endif 00199 00200 #warning reenable true negation 00201 #if 0 00202 BOOST_AUTO_TEST_CASE(testHexParserTrueNegation) 00203 { 00204 ProgramCtx ctx; 00205 ctx.setupRegistry(RegistryPtr(new Registry)); 00206 00207 std::stringstream ss; 00208 ss << 00209 "a. -b. -b :- a, -b, not -b, not a." << std::endl; 00210 InputProviderPtr ip(new InputProvider); 00211 ip->addStreamInput(ss, "testinput"); 00212 ModuleHexParser parser; 00213 BOOST_REQUIRE_NO_THROW(parser.parse(ip, ctx)); 00214 00215 LOG_REGISTRY_PROGRAM(ctx); 00216 00217 ID ida = ctx.registry()->ogatoms.getIDByString("a"); 00218 ID idmb = ctx.registry()->ogatoms.getIDByString("-b"); 00219 BOOST_REQUIRE((ida | idmb) != ID_FAIL); 00220 00221 // TODO: the following will become a bitset check 00222 BOOST_REQUIRE(ctx.edb.size() == 2); 00223 { 00224 BOOST_CHECK(ctx.edb[0] == ida); 00225 BOOST_CHECK(ctx.edb[1] == idmb); 00226 } 00227 00228 BOOST_REQUIRE(ctx.idb.size() == 1); 00229 { 00230 const Rule& r = ctx.registry()->rules.getByID(ctx.idb[0]); 00231 BOOST_CHECK(r.kind == (ID::MAINKIND_RULE | ID::SUBKIND_RULE_REGULAR)); 00232 BOOST_CHECK(r.weight == ID_FAIL); 00233 BOOST_CHECK(r.level == ID_FAIL); 00234 BOOST_REQUIRE(r.head.size() == 1); 00235 { 00236 BOOST_CHECK(r.head[0] == idmb); 00237 } 00238 BOOST_REQUIRE(r.body.size() == 4); 00239 { 00240 BOOST_CHECK(r.body[0] == ID::posLiteralFromAtom(ida)); 00241 BOOST_CHECK(r.body[1] == ID::posLiteralFromAtom(idmb)); 00242 BOOST_CHECK(r.body[2] == ID::nafLiteralFromAtom(idmb)); 00243 BOOST_CHECK(r.body[3] == ID::nafLiteralFromAtom(ida)); 00244 } 00245 } 00246 } 00247 #endif 00248 00249 BOOST_AUTO_TEST_CASE(testHexParserBuiltinPredicates) 00250 { 00251 ProgramCtx ctx; 00252 ctx.setupRegistry(RegistryPtr(new Registry)); 00253 00254 std::stringstream ss; 00255 ss << 00256 ":- X != 4, X < Y, >=(X,Y), #int(X)."; 00257 InputProviderPtr ip(new InputProvider); 00258 ip->addStreamInput(ss, "testinput"); 00259 ModuleHexParser parser; 00260 BOOST_REQUIRE_NO_THROW(parser.parse(ip, ctx)); 00261 00262 LOG_REGISTRY_PROGRAM(ctx); 00263 00264 ID idX = ctx.registry()->terms.getIDByString("X"); 00265 ID idY = ctx.registry()->terms.getIDByString("Y"); 00266 ID id4 = ID::termFromInteger(4); 00267 ID idne = ID::termFromBuiltin(ID::TERM_BUILTIN_NE); 00268 ID idlt = ID::termFromBuiltin(ID::TERM_BUILTIN_LT); 00269 ID idge = ID::termFromBuiltin(ID::TERM_BUILTIN_GE); 00270 ID idint = ID::termFromBuiltin(ID::TERM_BUILTIN_INT); 00271 BOOST_REQUIRE((idX | idY | id4 | idne | idlt | idge | idint) != ID_FAIL); 00272 00273 BOOST_REQUIRE(ctx.idb.size() == 1); 00274 { 00275 const Rule& r = ctx.registry()->rules.getByID(ctx.idb[0]); 00276 BOOST_CHECK(r.kind == (ID::MAINKIND_RULE | ID::SUBKIND_RULE_CONSTRAINT)); 00277 BOOST_CHECK(r.weight == ID_FAIL); 00278 BOOST_CHECK(r.level == ID_FAIL); 00279 BOOST_CHECK(r.head.size() == 0); 00280 BOOST_REQUIRE(r.body.size() == 4); 00281 { 00282 ID idlit = r.body[0]; 00283 BOOST_CHECK(idlit.isLiteral()); 00284 BOOST_CHECK(idlit.isBuiltinAtom()); 00285 const BuiltinAtom& at = ctx.registry()->batoms.getByID(idlit); 00286 BOOST_CHECK(ID(at.kind,0).isBuiltinAtom()); 00287 BOOST_REQUIRE(at.tuple.size() == 3); 00288 BOOST_CHECK(at.tuple[0] == idne); 00289 BOOST_CHECK(at.tuple[1] == idX); 00290 BOOST_CHECK(at.tuple[2] == id4); 00291 } 00292 { 00293 ID idlit = r.body[1]; 00294 BOOST_CHECK(idlit.isLiteral()); 00295 BOOST_CHECK(idlit.isBuiltinAtom()); 00296 const BuiltinAtom& at = ctx.registry()->batoms.getByID(idlit); 00297 BOOST_CHECK(ID(at.kind,0).isBuiltinAtom()); 00298 BOOST_REQUIRE(at.tuple.size() == 3); 00299 BOOST_CHECK(at.tuple[0] == idlt); 00300 BOOST_CHECK(at.tuple[1] == idX); 00301 BOOST_CHECK(at.tuple[2] == idY); 00302 } 00303 { 00304 ID idlit = r.body[2]; 00305 BOOST_CHECK(idlit.isLiteral()); 00306 BOOST_CHECK(idlit.isBuiltinAtom()); 00307 const BuiltinAtom& at = ctx.registry()->batoms.getByID(idlit); 00308 BOOST_CHECK(ID(at.kind,0).isBuiltinAtom()); 00309 BOOST_REQUIRE(at.tuple.size() == 3); 00310 BOOST_CHECK(at.tuple[0] == idge); 00311 BOOST_CHECK(at.tuple[1] == idX); 00312 BOOST_CHECK(at.tuple[2] == idY); 00313 } 00314 { 00315 ID idlit = r.body[3]; 00316 BOOST_CHECK(idlit.isLiteral()); 00317 BOOST_CHECK(idlit.isBuiltinAtom()); 00318 const BuiltinAtom& at = ctx.registry()->batoms.getByID(idlit); 00319 BOOST_CHECK(ID(at.kind,0).isBuiltinAtom()); 00320 BOOST_REQUIRE(at.tuple.size() == 2); 00321 BOOST_CHECK(at.tuple[0] == idint); 00322 BOOST_CHECK(at.tuple[1] == idX); 00323 } 00324 } 00325 } 00326 00327 BOOST_AUTO_TEST_CASE(testHexParserExternalAtoms) 00328 { 00329 ProgramCtx ctx; 00330 ctx.setupRegistry(RegistryPtr(new Registry)); 00331 00332 std::stringstream ss; 00333 ss << 00334 ":- &foo[a,b,X](b,X,4)."; 00335 InputProviderPtr ip(new InputProvider); 00336 ip->addStreamInput(ss, "testinput"); 00337 ModuleHexParser parser; 00338 BOOST_REQUIRE_NO_THROW(parser.parse(ip, ctx)); 00339 00340 LOG_REGISTRY_PROGRAM(ctx); 00341 00342 ID ida = ctx.registry()->terms.getIDByString("a"); 00343 ID idb = ctx.registry()->terms.getIDByString("b"); 00344 ID idX = ctx.registry()->terms.getIDByString("X"); 00345 ID id4 = ID::termFromInteger(4); 00346 ID idfoo = ctx.registry()->terms.getIDByString("foo"); 00347 BOOST_REQUIRE((ida | idb | idX | id4 | idfoo) != ID_FAIL); 00348 00349 BOOST_REQUIRE(ctx.idb.size() == 1); 00350 { 00351 const Rule& r = ctx.registry()->rules.getByID(ctx.idb[0]); 00352 BOOST_CHECK(r.kind == (ID::MAINKIND_RULE | ID::SUBKIND_RULE_CONSTRAINT | ID::PROPERTY_RULE_EXTATOMS)); 00353 BOOST_CHECK(r.weight == ID_FAIL); 00354 BOOST_CHECK(r.level == ID_FAIL); 00355 BOOST_CHECK(r.head.size() == 0); 00356 BOOST_REQUIRE(r.body.size() == 1); 00357 { 00358 ID idlit = r.body[0]; 00359 BOOST_CHECK(idlit.isLiteral()); 00360 BOOST_CHECK(idlit.isExternalAtom()); 00361 const ExternalAtom& at = ctx.registry()->eatoms.getByID(idlit); 00362 BOOST_CHECK(ID(at.kind,0).isExternalAtom()); 00363 BOOST_CHECK(at.predicate == idfoo); 00364 BOOST_REQUIRE(at.inputs.size() == 3); 00365 BOOST_CHECK(at.inputs[0] == ida); 00366 BOOST_CHECK(at.inputs[1] == idb); 00367 BOOST_CHECK(at.inputs[2] == idX); 00368 BOOST_REQUIRE(at.tuple.size() == 3); 00369 BOOST_CHECK(at.tuple[0] == idb); 00370 BOOST_CHECK(at.tuple[1] == idX); 00371 BOOST_CHECK(at.tuple[2] == id4); 00372 } 00373 } 00374 } 00375