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 <clasp/dependency_graph.h>
00022 #include <clasp/solver.h>
00023 namespace Clasp { namespace Test {
00024 using namespace Clasp::Asp;
00025 class DependencyGraphTest : public CppUnit::TestFixture {
00026 CPPUNIT_TEST_SUITE(DependencyGraphTest);
00027 CPPUNIT_TEST(testTightProgram);
00028 CPPUNIT_TEST(testInitOrder);
00029 CPPUNIT_TEST(testProgramWithLoops);
00030 CPPUNIT_TEST(testWithSimpleCardinalityConstraint);
00031 CPPUNIT_TEST(testWithSimpleWeightConstraint);
00032 CPPUNIT_TEST_SUITE_END();
00033 public:
00034 DependencyGraphTest() {
00035 }
00036 void setUp() {
00037 ctx = new SharedContext();
00038 }
00039 void tearDown() {
00040 delete ctx;
00041 }
00042 void testTightProgram() {
00043 builder.start(*ctx)
00044 .setAtomName(1, "a").setAtomName(2, "b")
00045 .startRule().addHead(1).addToBody(2, false).endRule()
00046 .endProgram();
00047 CPPUNIT_ASSERT_EQUAL(true, builder.stats.sccs == 0);
00048 CPPUNIT_ASSERT(ctx->sccGraph.get() == 0);
00049 }
00050
00051 void testInitOrder() {
00052 builder.start(*ctx, LogicProgram::AspOptions().noEq())
00053 .setAtomName(1,"a").setAtomName(2,"b").setAtomName(3,"x").setAtomName(4,"y")
00054 .startRule().addHead(4).addToBody(3, true).endRule()
00055 .startRule().addHead(3).addToBody(4, true).endRule()
00056 .startRule().addHead(2).addToBody(3, true).endRule()
00057 .startRule().addHead(2).addToBody(1, true).endRule()
00058 .startRule().addHead(1).addToBody(2, true).endRule()
00059 .startRule().addHead(3).addToBody(1, false).endRule()
00060 .endProgram();
00061
00062 CPPUNIT_ASSERT_EQUAL(true, builder.stats.sccs == 2);
00063
00064 DG* graph = ctx->sccGraph.get();
00065
00066 CPPUNIT_ASSERT_EQUAL(uint32(10), graph->nodes());
00067
00068 const DG::AtomNode& b = graph->getAtom(builder.getAtom(2)->id());
00069 const DG::AtomNode& x = graph->getAtom(builder.getAtom(3)->id());
00070
00071 CPPUNIT_ASSERT(graph->getBody(b.body(0)).scc != b.scc);
00072 CPPUNIT_ASSERT(graph->getBody(b.body(1)).scc == b.scc);
00073 CPPUNIT_ASSERT(b.bodies_begin()+2 == b.bodies_end());
00074
00075 CPPUNIT_ASSERT(graph->getBody(x.body(0)).scc != x.scc);
00076 CPPUNIT_ASSERT(graph->getBody(x.body(1)).scc == x.scc);
00077 CPPUNIT_ASSERT(x.bodies_begin()+2 == x.bodies_end());
00078
00079 const DG::BodyNode& xBody = graph->getBody(b.body(0));
00080 CPPUNIT_ASSERT(graph->getAtom(xBody.heads_begin()[0]).scc == xBody.scc);
00081 CPPUNIT_ASSERT(graph->getAtom(xBody.heads_begin()[1]).scc != xBody.scc);
00082 CPPUNIT_ASSERT(xBody.heads_begin()+2 == xBody.heads_end());
00083 }
00084
00085 void testProgramWithLoops() {
00086 builder.start(*ctx)
00087 .setAtomName(1, "a").setAtomName(2, "b").setAtomName(3, "c")
00088 .setAtomName(4, "d").setAtomName(5, "g").setAtomName(6, "x").setAtomName(7, "y")
00089 .startRule().addHead(1).addToBody(6, false).endRule()
00090 .startRule().addHead(2).addToBody(1, true).endRule()
00091 .startRule().addHead(1).addToBody(2, true).addToBody(4, true).endRule()
00092 .startRule().addHead(2).addToBody(5, false).endRule()
00093 .startRule().addHead(3).addToBody(6, true).endRule()
00094 .startRule().addHead(4).addToBody(3, true).endRule()
00095 .startRule().addHead(3).addToBody(4, true).endRule()
00096 .startRule().addHead(4).addToBody(5, false).endRule()
00097 .startRule().addHead(7).addToBody(5, false).endRule()
00098 .startRule().addHead(6).addToBody(7, true).endRule()
00099 .startRule().addHead(5).addToBody(7, false).endRule()
00100 .endProgram();
00101
00102 SymbolTable& index = ctx->symbolTable();
00103 DG* graph = ctx->sccGraph.get();
00104 CPPUNIT_ASSERT_EQUAL(index[6].lit, index[7].lit);
00105 CPPUNIT_ASSERT_EQUAL(~index[6].lit, index[5].lit);
00106
00107 CPPUNIT_ASSERT( graph->getAtom(builder.getAtom(1)->id()).scc == 0 );
00108 CPPUNIT_ASSERT( graph->getAtom(builder.getAtom(2)->id()).scc == 0 );
00109 CPPUNIT_ASSERT( graph->getAtom(builder.getAtom(3)->id()).scc == 1 );
00110 CPPUNIT_ASSERT( graph->getAtom(builder.getAtom(4)->id()).scc == 1 );
00111 CPPUNIT_ASSERT( builder.getAtom(5)->id() == PrgNode::maxVertex );
00112 CPPUNIT_ASSERT( builder.getAtom(6)->eq() || builder.getAtom(6)->id() == PrgNode::maxVertex );
00113 CPPUNIT_ASSERT( builder.getAtom(7)->id() == PrgNode::maxVertex );
00114
00115 CPPUNIT_ASSERT(uint32(11) == graph->nodes());
00116
00117 const DG::AtomNode& a = graph->getAtom(builder.getAtom(1)->id());
00118 CPPUNIT_ASSERT(graph->getBody(a.body(0)).scc == PrgNode::noScc);
00119 CPPUNIT_ASSERT(graph->getBody(a.body(1)).scc == a.scc);
00120 CPPUNIT_ASSERT(a.bodies_begin()+2 == a.bodies_end());
00121 CPPUNIT_ASSERT_EQUAL(true, ctx->varInfo(a.lit.var()).frozen());
00122
00123 const DG::BodyNode& bd = graph->getBody(a.body(1));
00124 CPPUNIT_ASSERT_EQUAL(true, ctx->varInfo(bd.lit.var()).frozen());
00125 CPPUNIT_ASSERT(graph->getAtom(bd.preds()[0]).lit == index[2].lit);
00126 CPPUNIT_ASSERT(bd.preds()[1]== idMax);
00127 CPPUNIT_ASSERT(bd.heads_begin()[0] == graph->id(a));
00128 CPPUNIT_ASSERT(bd.heads_begin()+1 == bd.heads_end());
00129 }
00130
00131 void testWithSimpleCardinalityConstraint() {
00132 builder.start(*ctx)
00133 .setAtomName(1, "a").setAtomName(2, "b")
00134 .startRule(CHOICERULE).addHead(2).endRule()
00135 .startRule(CONSTRAINTRULE, 1).addHead(1).addToBody(1, true).addToBody(2,true).endRule()
00136 ;
00137 CPPUNIT_ASSERT_EQUAL(true, builder.endProgram());
00138 DG* graph = ctx->sccGraph.get();
00139 CPPUNIT_ASSERT( uint32(3) == graph->nodes() );
00140 SymbolTable& index = ctx->symbolTable();
00141 const DG::AtomNode& a = graph->getAtom(builder.getAtom(1)->id());
00142 const DG::BodyNode& body = graph->getBody(a.body(0));
00143
00144 CPPUNIT_ASSERT(body.num_preds() == 2);
00145 CPPUNIT_ASSERT(body.extended());
00146 CPPUNIT_ASSERT(body.ext_bound() == 1);
00147 CPPUNIT_ASSERT(body.pred_inc() == 1);
00148 CPPUNIT_ASSERT(body.preds()[0] == graph->id(a));
00149 CPPUNIT_ASSERT(body.preds()[1] == idMax);
00150 CPPUNIT_ASSERT(body.preds()[2] == index[2].lit.asUint());
00151 CPPUNIT_ASSERT(body.preds()[3] == idMax);
00152 CPPUNIT_ASSERT(body.pred_weight(0,false) == 1);
00153 CPPUNIT_ASSERT(body.pred_weight(1,true) == 1);
00154
00155 CPPUNIT_ASSERT(a.inExtended());
00156 CPPUNIT_ASSERT(a.succs()[0] == idMax);
00157 CPPUNIT_ASSERT(a.succs()[1] == a.body(0));
00158 CPPUNIT_ASSERT(a.succs()[2] == 0);
00159 CPPUNIT_ASSERT(a.succs()[3] == idMax);
00160 }
00161
00162 void testWithSimpleWeightConstraint() {
00163 builder.start(*ctx)
00164 .setAtomName(1, "a").setAtomName(2, "b").setAtomName(3, "c")
00165 .startRule(CHOICERULE).addHead(2).addHead(3).endRule()
00166 .startRule(WEIGHTRULE, 2).addHead(1).addToBody(1, true, 2).addToBody(2,true, 2).addToBody(3, true, 1).endRule()
00167 ;
00168 CPPUNIT_ASSERT_EQUAL(true, builder.endProgram());
00169 DG* graph = ctx->sccGraph.get();
00170 CPPUNIT_ASSERT( uint32(3) == graph->nodes() );
00171
00172 SymbolTable& index = ctx->symbolTable();
00173 const DG::AtomNode& a = graph->getAtom(builder.getAtom(1)->id());
00174 const DG::BodyNode& body = graph->getBody(a.body(0));
00175
00176 CPPUNIT_ASSERT(body.num_preds() == 3);
00177 CPPUNIT_ASSERT(body.extended());
00178 CPPUNIT_ASSERT(body.ext_bound() == 2);
00179 CPPUNIT_ASSERT(body.pred_inc() == 2);
00180 CPPUNIT_ASSERT(body.preds()[0] == graph->id(a));
00181 CPPUNIT_ASSERT(body.preds()[2] == idMax);
00182 CPPUNIT_ASSERT(body.preds()[3] == index[2].lit.asUint());
00183 CPPUNIT_ASSERT(body.preds()[5] == index[3].lit.asUint());
00184 CPPUNIT_ASSERT(body.preds()[7] == idMax);
00185 CPPUNIT_ASSERT(body.pred_weight(0, false) == 2);
00186 CPPUNIT_ASSERT(body.pred_weight(1, true) == 2);
00187 CPPUNIT_ASSERT(body.pred_weight(2, true) == 1);
00188
00189 CPPUNIT_ASSERT(a.inExtended());
00190 CPPUNIT_ASSERT(a.succs()[0] == idMax);
00191 CPPUNIT_ASSERT(a.succs()[1] == a.body(0));
00192 CPPUNIT_ASSERT(a.succs()[2] == 0);
00193 CPPUNIT_ASSERT(a.succs()[3] == idMax);
00194 }
00195 private:
00196 typedef SharedDependencyGraph DG;
00197 SharedContext* ctx;
00198 LogicProgram builder;
00199 };
00200 CPPUNIT_TEST_SUITE_REGISTRATION(DependencyGraphTest);
00201 } }