parser_test.cpp
Go to the documentation of this file.
00001 // 
00002 // Copyright (c) 2006, Benjamin Kaufmann
00003 // 
00004 // This file is part of Clasp. See http://www.cs.uni-potsdam.de/clasp/ 
00005 // 
00006 // Clasp is free software; you can redistribute it and/or modify
00007 // it under the terms of the GNU General Public License as published by
00008 // the Free Software Foundation; either version 2 of the License, or
00009 // (at your option) any later version.
00010 // 
00011 // Clasp is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 // GNU General Public License for more details.
00015 // 
00016 // You should have received a copy of the GNU General Public License
00017 // along with Clasp; if not, write to the Free Software
00018 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
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" // d:-not c.
00066                     << "1 2 1 1 3 \n" // c:-not a.
00067                     << "1 3 1 1 4 \n" // a:-not b.
00068                     << "1 4 1 1 3 \n" // b:-not a.
00069                     << "0\n1 d\n2 c\n3 a\n4 b\n"
00070                     << "0\nB+\n0\nB-\n2\n0\n1\n"; // B-: c
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"// a :- 2 {not c, b, d}
00084                     << "1 2 1 1 3 \n"      // b :- not c.
00085                     << "1 3 1 1 2 \n"      // c :- not b.
00086                     << "1 4 1 1 3 \n"      // d :- not c.
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" // a :- not c.
00097                     << "1 3 1 1 1 \n" // c :- not b.
00098                     << "1 2 1 0 1 \n" // b :- a.
00099                     << "1 4 1 0 1 \n" // d :- a.
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"// a :- 2 [b=1, not c=2, d=3]
00110                     << "1 2 1 1 3 \n" // b :- not c.
00111                     << "1 3 1 1 2 \n" // c :- not b.
00112                     << "1 4 1 1 3 \n" // d :- not c.
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" // a :- not c.
00122                     << "1 3 1 1 1 \n" // c :- not a.
00123                     << "1 2 1 0 1 \n" // b :- a.
00124                     << "1 4 1 0 1 \n" // d :- a.
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"// {a,b,c} :- b, not c.
00135                     << "1 2 1 1 1 \n" // b :- not a.
00136                     << "1 3 1 1 2 \n" // c :- not b.
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"   // b.
00144                     << "1 4 1 0 2 \n" // _a :- b
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"// a :- 2 {c, b, d}
00155                     << "1 2 1 1 3 \n" // b :- not c.
00156                     << "1 3 1 1 2 \n" // c :- not b.
00157                     << "1 4 1 1 3 \n" // d :- not c.
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"// a :- 2 [c = 1, b = 2]
00168                     << "1 2 1 1 3 \n" // b :- not c.
00169                     << "1 3 1 1 2 \n" // c :- not b.
00170                     << "1 4 1 0 2 \n" // d :- b.
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"// a :- 2 [c = 2, b = 1, d = 3], but (d = 3 -> d = 2)
00181                     << "1 2 1 1 3 \n" // b :- not c.
00182                     << "1 3 1 1 2 \n" // c :- not b.
00183                     << "1 4 1 1 3 \n" // d :- not c.
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"// a :- 2 [c = 2, b = 3]
00194                     << "1 2 1 1 3 \n" // b :- not c.
00195                     << "1 3 1 1 2 \n" // c :- not b.
00196                     << "1 4 1 0 2 \n" // d :- b.
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"// {a,b,c} :- b, not c.
00207                     << "1 2 1 1 1 \n" // b :- not a.
00208                     << "1 3 1 1 2 \n" // c :- not b.
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"// b.
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 } } 


clasp
Author(s): Benjamin Kaufmann
autogenerated on Thu Aug 27 2015 12:41:39