00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "test.h"
00021 #include <sstream>
00022 #include <clasp/parser.h>
00023 #include <clasp/logic_program.h>
00024 #include <clasp/minimize_constraint.h>
00025 #include <clasp/solver.h>
00026 namespace Clasp { namespace Test {
00027
00028 class LparseParserTest : public CppUnit::TestFixture {
00029
00030 CPPUNIT_TEST_SUITE(LparseParserTest);
00031 CPPUNIT_TEST(testEmptyLparse);
00032 CPPUNIT_TEST(testSingleFact);
00033 CPPUNIT_TEST(testComputeStatementAssumptions);
00034 CPPUNIT_TEST(testTransformSimpleConstraintRule);
00035 CPPUNIT_TEST(testTransformSimpleWeightRule);
00036 CPPUNIT_TEST(testTransformSimpleChoiceRule);
00037 CPPUNIT_TEST(testSimpleConstraintRule);
00038 CPPUNIT_TEST(testSimpleWeightRule);
00039 CPPUNIT_TEST(testSimpleChoiceRule);
00040 CPPUNIT_TEST_SUITE_END();
00041
00042 public:
00043 void setUp() {
00044 api.start(ctx, Asp::LogicProgram::AspOptions().noScc());
00045 }
00046 void testEmptyLparse() {
00047 std::stringstream empty("0\n0\nB+\n0\nB-\n0\n1\n");
00048 CPPUNIT_ASSERT_EQUAL(true, Input_t::parseLparse(empty, api));
00049 empty.clear();
00050 std::stringstream out;
00051 api.endProgram();
00052 api.write(out);
00053 CPPUNIT_ASSERT_EQUAL(empty.str(), out.str());
00054 }
00055
00056 void testSingleFact() {
00057 std::stringstream prg("1 1 0 0 \n0\n1 a\n0\nB+\n0\nB-\n0\n1\n");
00058 CPPUNIT_ASSERT_EQUAL(true, Input_t::parseLparse(prg, api));
00059 api.endProgram();
00060 CPPUNIT_ASSERT_EQUAL(0u, ctx.numVars());
00061 CPPUNIT_ASSERT_EQUAL('a', ctx.symbolTable()[1].name[0]);
00062 }
00063 void testComputeStatementAssumptions() {
00064 std::stringstream prg;
00065 prg << "1 1 1 1 2 \n"
00066 << "1 2 1 1 3 \n"
00067 << "1 3 1 1 4 \n"
00068 << "1 4 1 1 3 \n"
00069 << "0\n1 d\n2 c\n3 a\n4 b\n"
00070 << "0\nB+\n0\nB-\n2\n0\n1\n";
00071
00072 CPPUNIT_ASSERT_EQUAL(true, Input_t::parseLparse(prg, api));
00073 api.endProgram() && ctx.endInit();
00074 CPPUNIT_ASSERT_EQUAL(true, ctx.master()->isTrue(ctx.symbolTable()[3].lit));
00075 CPPUNIT_ASSERT_EQUAL(true, ctx.master()->isTrue(ctx.symbolTable()[1].lit));
00076 CPPUNIT_ASSERT_EQUAL(true, ctx.master()->isFalse(ctx.symbolTable()[2].lit));
00077 CPPUNIT_ASSERT_EQUAL(true, ctx.master()->isFalse(ctx.symbolTable()[4].lit));
00078 }
00079
00080
00081 void testTransformSimpleConstraintRule() {
00082 std::stringstream prg;
00083 prg << "2 1 3 1 2 3 2 4 \n"
00084 << "1 2 1 1 3 \n"
00085 << "1 3 1 1 2 \n"
00086 << "1 4 1 1 3 \n"
00087 << "0\n1 a\n2 b\n3 c\n4 d\n"
00088 << "0\nB+\n0\nB-\n0\n1\n";
00089
00090 std::stringstream exp, out;
00091 api.setExtendedRuleMode(Asp::LogicProgram::mode_transform_weight);
00092 CPPUNIT_ASSERT_EQUAL(true, Input_t::parseLparse(prg, api));
00093 CPPUNIT_ASSERT_EQUAL(true, api.endProgram());
00094 CPPUNIT_ASSERT(ctx.symbolTable()[2].lit == ctx.symbolTable()[1].lit);
00095 CPPUNIT_ASSERT(ctx.symbolTable()[4].lit == ctx.symbolTable()[1].lit);
00096 exp << "1 1 1 1 3 \n"
00097 << "1 3 1 1 1 \n"
00098 << "1 2 1 0 1 \n"
00099 << "1 4 1 0 1 \n"
00100 << "0\n1 a\n2 b\n3 c\n4 d\n0\n"
00101 << "B+\n0\nB-\n0\n1\n"
00102 ;
00103 api.write(out);
00104 CPPUNIT_ASSERT_EQUAL(exp.str(), out.str());
00105 }
00106
00107 void testTransformSimpleWeightRule() {
00108 std::stringstream prg;
00109 prg << "5 1 2 3 1 3 2 4 2 1 3\n"
00110 << "1 2 1 1 3 \n"
00111 << "1 3 1 1 2 \n"
00112 << "1 4 1 1 3 \n"
00113 << "0\n1 a\n2 b\n3 c\n4 d\n"
00114 << "0\nB+\n0\nB-\n0\n1\n";
00115 api.setExtendedRuleMode(Asp::LogicProgram::mode_transform_weight);
00116 CPPUNIT_ASSERT_EQUAL(true, Input_t::parseLparse(prg, api));
00117 CPPUNIT_ASSERT_EQUAL(true, api.endProgram());
00118 CPPUNIT_ASSERT_EQUAL(1u, ctx.numVars());
00119
00120 std::stringstream exp, out;
00121 exp << "1 1 1 1 3 \n"
00122 << "1 3 1 1 1 \n"
00123 << "1 2 1 0 1 \n"
00124 << "1 4 1 0 1 \n"
00125 << "0\n1 a\n2 b\n3 c\n4 d\n0\n"
00126 << "B+\n0\nB-\n0\n1\n"
00127 ;
00128 api.write(out);
00129 CPPUNIT_ASSERT_EQUAL(exp.str(), out.str());
00130 }
00131
00132 void testTransformSimpleChoiceRule() {
00133 std::stringstream prg;
00134 prg << "3 3 1 2 3 2 1 3 2 \n"
00135 << "1 2 1 1 1 \n"
00136 << "1 3 1 1 2 \n"
00137 << "0\n1 a\n2 b\n3 c\n"
00138 << "0\nB+\n0\nB-\n0\n1\n";
00139 api.setExtendedRuleMode(Asp::LogicProgram::mode_transform_choice);
00140 CPPUNIT_ASSERT_EQUAL(true, Input_t::parseLparse(prg, api));
00141 CPPUNIT_ASSERT_EQUAL(true, api.endProgram());
00142 std::stringstream exp, out;
00143 exp << "1 2 0 0 \n"
00144 << "1 4 1 0 2 \n"
00145 << "0\n2 b\n0\n"
00146 << "B+\n2\n0\nB-\n0\n1\n"
00147 ;
00148 api.write(out);
00149 CPPUNIT_ASSERT_EQUAL(exp.str(), out.str());
00150 }
00151
00152 void testSimpleConstraintRule() {
00153 std::stringstream prg;
00154 prg << "2 1 3 0 2 3 2 4 \n"
00155 << "1 2 1 1 3 \n"
00156 << "1 3 1 1 2 \n"
00157 << "1 4 1 1 3 \n"
00158 << "0\n1 a\n2 b\n3 c\n4 d\n"
00159 << "0\nB+\n0\nB-\n0\n1\n";
00160
00161 std::stringstream exp, out;
00162 api.setExtendedRuleMode(Asp::LogicProgram::mode_transform_choice);
00163 CPPUNIT_ASSERT_EQUAL(true, Input_t::parseLparse(prg, api));
00164 CPPUNIT_ASSERT_EQUAL(true, api.endProgram());
00165 CPPUNIT_ASSERT_EQUAL(2u, ctx.numVars());
00166
00167 exp << "5 1 2 2 0 3 2 1 2 \n"
00168 << "1 2 1 1 3 \n"
00169 << "1 3 1 1 2 \n"
00170 << "1 4 1 0 2 \n"
00171 << "0\n1 a\n2 b\n3 c\n4 d\n0\n"
00172 << "B+\n0\nB-\n0\n1\n"
00173 ;
00174 api.write(out);
00175 CPPUNIT_ASSERT_EQUAL(exp.str(), out.str());
00176 }
00177
00178 void testSimpleWeightRule() {
00179 std::stringstream prg;
00180 prg << "5 1 2 3 0 3 2 4 2 1 3\n"
00181 << "1 2 1 1 3 \n"
00182 << "1 3 1 1 2 \n"
00183 << "1 4 1 1 3 \n"
00184 << "0\n1 a\n2 b\n3 c\n4 d\n"
00185 << "0\nB+\n0\nB-\n0\n1\n";
00186
00187 std::stringstream exp, out;
00188 api.setExtendedRuleMode(Asp::LogicProgram::mode_transform_choice);
00189 CPPUNIT_ASSERT_EQUAL(true, Input_t::parseLparse(prg, api));
00190 CPPUNIT_ASSERT_EQUAL(true, api.endProgram());
00191 CPPUNIT_ASSERT_EQUAL(2u, ctx.numVars());
00192
00193 exp << "5 1 2 2 0 3 2 2 3 \n"
00194 << "1 2 1 1 3 \n"
00195 << "1 3 1 1 2 \n"
00196 << "1 4 1 0 2 \n"
00197 << "0\n1 a\n2 b\n3 c\n4 d\n0\n"
00198 << "B+\n0\nB-\n0\n1\n"
00199 ;
00200 api.write(out);
00201 CPPUNIT_ASSERT_EQUAL(exp.str(), out.str());
00202 }
00203
00204 void testSimpleChoiceRule() {
00205 std::stringstream prg;
00206 prg << "3 3 1 2 3 2 1 3 2 \n"
00207 << "1 2 1 1 1 \n"
00208 << "1 3 1 1 2 \n"
00209 << "0\n1 a\n2 b\n3 c\n"
00210 << "0\nB+\n0\nB-\n0\n1\n";
00211
00212 api.setExtendedRuleMode(Asp::LogicProgram::mode_transform_weight);
00213 CPPUNIT_ASSERT_EQUAL(true, Input_t::parseLparse(prg, api));
00214 CPPUNIT_ASSERT_EQUAL(true, api.endProgram());
00215 std::stringstream exp, out;
00216 prg.clear();
00217 prg.seekg(0);
00218 exp << "1 2 0 0 \n"
00219 << "0\n2 b\n"
00220 << "0\n"
00221 << "B+\n2\n0\nB-\n0\n1\n";
00222 api.write(out);
00223 CPPUNIT_ASSERT_EQUAL(exp.str(), out.str());
00224 }
00225 private:
00226 SharedContext ctx;
00227 Asp::LogicProgram api;
00228 };
00229
00230 class DimacsParserTest : public CppUnit::TestFixture {
00231
00232 CPPUNIT_TEST_SUITE(DimacsParserTest);
00233 CPPUNIT_TEST(testDimacs);
00234 CPPUNIT_TEST(testDimacsDontAddTaut);
00235 CPPUNIT_TEST(testDimacsDontAddDupLit);
00236 CPPUNIT_TEST(testDimacsBadVars);
00237
00238 CPPUNIT_TEST(testWcnf);
00239 CPPUNIT_TEST(testPartialWcnf);
00240 CPPUNIT_TEST_SUITE_END();
00241
00242 public:
00243 void setUp() {
00244 api.startProgram(ctx);
00245 }
00246 void testDimacs() {
00247 std::stringstream prg;
00248 prg << "c simple test case\n"
00249 << "p cnf 4 3\n"
00250 << "1 2 0\n"
00251 << "3 4 0\n"
00252 << "-1 -2 -3 -4 0\n";
00253 CPPUNIT_ASSERT(Input_t::parseDimacs(prg, api) && api.endProgram());
00254 CPPUNIT_ASSERT(ctx.numVars() == 4);
00255 CPPUNIT_ASSERT(ctx.numConstraints() == 3);
00256 }
00257
00258 void testDimacsDontAddTaut() {
00259 std::stringstream prg;
00260 prg << "c simple test case\n"
00261 << "p cnf 4 4\n"
00262 << "1 2 0\n"
00263 << "3 4 0\n"
00264 << "-1 -2 -3 -4 0\n"
00265 << "1 -2 -3 2 0\n";
00266 CPPUNIT_ASSERT(Input_t::parseDimacs(prg, api) && api.endProgram());
00267 CPPUNIT_ASSERT(ctx.numVars() == 4);
00268 CPPUNIT_ASSERT(ctx.numConstraints() == 3);
00269 }
00270
00271 void testDimacsDontAddDupLit() {
00272 std::stringstream prg;
00273 prg << "c simple test case\n"
00274 << "p cnf 2 4\n"
00275 << "1 2 2 1 0\n"
00276 << "1 2 1 2 0\n"
00277 << "-1 -2 -1 0\n"
00278 << "-2 -1 -2 0\n";
00279 CPPUNIT_ASSERT(Input_t::parseDimacs(prg, api) && api.endProgram());
00280 CPPUNIT_ASSERT(ctx.numVars() == 2);
00281 CPPUNIT_ASSERT(ctx.numConstraints() == 4);
00282 CPPUNIT_ASSERT(ctx.numBinary() == 4);
00283 }
00284
00285 void testDimacsBadVars() {
00286 std::stringstream prg;
00287 prg << "p cnf 2 1\n"
00288 << "3 4 0\n";
00289 CPPUNIT_ASSERT_THROW(Input_t::parseDimacs(prg, api), ParseError);
00290 }
00291
00292 void testWcnf() {
00293 std::stringstream prg;
00294 prg << "c comments Weighted Max-SAT\n"
00295 << "p wcnf 3 5\n"
00296 << "10 1 -2 0\n"
00297 << "3 -1 2 -3 0\n"
00298 << "8 -3 2 0\n"
00299 << "5 1 3 0\n"
00300 << "2 3 0\n";
00301 CPPUNIT_ASSERT(Input_t::parseDimacs(prg, api) && api.endProgram());
00302 CPPUNIT_ASSERT(ctx.numVars() == 7);
00303 CPPUNIT_ASSERT(ctx.symbolTable().size() == 4);
00304 CPPUNIT_ASSERT(ctx.numConstraints() == 4);
00305
00306 SharedMinimizeData* wLits = api.getMinimizeConstraint();
00307 CPPUNIT_ASSERT(wLits->numRules() == 1);
00308 CPPUNIT_ASSERT(wLits->lits[0].second == 10);
00309 CPPUNIT_ASSERT(wLits->lits[1].second == 8);
00310 CPPUNIT_ASSERT(wLits->lits[2].second == 5);
00311 CPPUNIT_ASSERT(wLits->lits[3].second == 3);
00312 }
00313
00314 void testPartialWcnf() {
00315 std::stringstream prg;
00316 prg << "c comments Weigthed Partial Max-SAT\n"
00317 << "p wcnf 4 5 16\n"
00318 << "16 1 -2 4 0\n"
00319 << "16 -1 -2 3 0\n"
00320 << "8 -2 -4 0\n"
00321 << "4 -3 2 0\n"
00322 << "1 1 3 0\n";
00323 CPPUNIT_ASSERT(Input_t::parseDimacs(prg, api) && api.endProgram());
00324 CPPUNIT_ASSERT(ctx.numVars() == 7);
00325 CPPUNIT_ASSERT(ctx.symbolTable().size() == 5);
00326 CPPUNIT_ASSERT(ctx.numConstraints() == 5);
00327 SharedMinimizeData* wLits = api.getMinimizeConstraint();
00328 CPPUNIT_ASSERT(wLits->numRules() == 1);
00329 CPPUNIT_ASSERT(wLits->lits[0].second == 8);
00330 CPPUNIT_ASSERT(wLits->lits[1].second == 4);
00331 CPPUNIT_ASSERT(wLits->lits[2].second == 1);
00332 }
00333 private:
00334 SharedContext ctx;
00335 SatBuilder api;
00336 };
00337
00338 class OPBParserTest : public CppUnit::TestFixture {
00339
00340 CPPUNIT_TEST_SUITE(OPBParserTest);
00341 CPPUNIT_TEST(testWBO);
00342 CPPUNIT_TEST(testNLC);
00343 CPPUNIT_TEST(testNLCUnsorted);
00344 CPPUNIT_TEST(testPBEqualityBug);
00345 CPPUNIT_TEST_SUITE_END();
00346
00347 public:
00348 void setUp() {
00349 api.startProgram(ctx);
00350 }
00351 void testWBO() {
00352 std::stringstream prg;
00353 prg << "* #variable= 1 #constraint= 2 #soft= 2 mincost= 2 maxcost= 3 sumcost= 5\n"
00354 << "soft: 6 ;\n"
00355 << "[2] +1 x1 >= 1 ;\n"
00356 << "[3] -1 x1 >= 0 ;\n";
00357 CPPUNIT_ASSERT(Input_t::parseOPB(prg, api) && api.endProgram());
00358 CPPUNIT_ASSERT(ctx.numVars() == 3);
00359 CPPUNIT_ASSERT(ctx.numConstraints() == 0 || ctx.numConstraints() == 2);
00360 CPPUNIT_ASSERT(ctx.symbolTable().size() == 2);
00361 SumVec bound;
00362 SharedMinimizeData* wLits = api.getMinimizeConstraint(&bound);
00363 CPPUNIT_ASSERT(wLits && wLits->numRules() == 1);
00364 CPPUNIT_ASSERT(wLits->adjust(0) == 2);
00365 CPPUNIT_ASSERT(bound.size() == 1 && bound[0] == 5);
00366 }
00367
00368 void testNLC() {
00369 std::stringstream prg;
00370 prg << "* #variable= 5 #constraint= 4 #product= 5 sizeproduct= 13\n"
00371 << "1 x1 +4 x1 ~x2 -2 x5 >=1;\n"
00372 << "-1 x1 +4 x2 -2 x5 >= 3;\n"
00373 << "10 x4 +4 x3 >= 10;\n"
00374 << "2 x2 x3 +3 x4 ~x5 +2 ~x1 x2 +3 ~x1 x2 x3 ~x4 ~x5 >= 1 ;\n";
00375 CPPUNIT_ASSERT(Input_t::parseOPB(prg, api) && api.endProgram());
00376 CPPUNIT_ASSERT(ctx.numVars() == 10);
00377 CPPUNIT_ASSERT(ctx.numConstraints() >= 4);
00378 CPPUNIT_ASSERT(ctx.symbolTable().size() == 6);
00379 }
00380
00381 void testNLCUnsorted() {
00382 std::stringstream prg;
00383 prg << "* #variable= 4 #constraint= 2 #product= 2 sizeproduct= 8\n"
00384 << "1 x1 +1 x2 x1 >=1;\n"
00385 << "1 x1 +1 x2 x3 x4 ~x4 x2 x3 >=1;\n";
00386 CPPUNIT_ASSERT(Input_t::parseOPB(prg, api) && api.endProgram());
00387 CPPUNIT_ASSERT(ctx.numVars() == 6);
00388 CPPUNIT_ASSERT(ctx.master()->isTrue(posLit(1)));
00389 CPPUNIT_ASSERT(ctx.master()->isFalse(posLit(6)));
00390 }
00391
00392 void testPBEqualityBug() {
00393 std::stringstream prg;
00394 prg << "* #variable= 4 #constraint= 2\n"
00395 << "+1 x1 = 1;\n"
00396 << "+1 x1 +1 x2 +1 x3 +1 x4 = 1;\n";
00397 CPPUNIT_ASSERT(Input_t::parseOPB(prg, api) && api.endProgram());
00398 CPPUNIT_ASSERT(ctx.master()->isTrue(posLit(1)));
00399 CPPUNIT_ASSERT(ctx.master()->isFalse(posLit(2)));
00400 CPPUNIT_ASSERT(ctx.master()->isFalse(posLit(3)));
00401 CPPUNIT_ASSERT(ctx.master()->isFalse(posLit(4)));
00402 }
00403 private:
00404 SharedContext ctx;
00405 PBBuilder api;
00406 };
00407
00408 CPPUNIT_TEST_SUITE_REGISTRATION(LparseParserTest);
00409 CPPUNIT_TEST_SUITE_REGISTRATION(DimacsParserTest);
00410 CPPUNIT_TEST_SUITE_REGISTRATION(OPBParserTest);
00411
00412 } }