Example #1
0
bool SolveAlgorithm::solve(SharedContext& ctx, const SolveParams& p, const LitVec& assume) {
	assumptions_ = assume;
	if (!isSentinel(ctx.tagLiteral())) { assumptions_.push_back(ctx.tagLiteral()); }
	bool more = limits_.conflicts == 0 || doSolve(*ctx.master(), p);
	ctx.enumerator()->reportResult(!more);
	if (!isSentinel(ctx.tagLiteral())) { assumptions_.pop_back(); }
	ctx.detach(*ctx.master());
	return more;
}
Example #2
0
uint32 SharedDependencyGraph::addBody(SharedContext& ctx, PrgBodyNode* b, const AtomList& prgAtoms) {
	if (b->visited()) {       // first time we see this body - 
		b->setVisited(false);   // mark as visited and create node
		b->setUfsNode( (NodeId)bodies_.size(), false );
		bodies_.push_back(BodyNode(b));
		BodyNode* bn = &bodies_.back();
		// Init node
		VarVec preds, succs;
		if (bn->scc != PrgNode::noScc) {
			const bool weights = b->type() == PrgBodyNode::SUM_BODY;
			for (uint32 p = 0; p != b->posSize(); ++p) {
				PrgAtomNode* pred = prgAtoms[b->pos(p)];
				if (relevantPrgAtom(*ctx.master(), pred) && pred->scc() == bn->scc) {
					preds.push_back( pred->ufsNode() );
					if (weights) {
						preds.push_back( b->weight(p, true) );
					}
				}
			}
			preds.push_back(idMax);
			if (bn->extended()) {
				for (uint32 n = 0; n != b->size(); ++n) {
					PrgAtomNode* pred = prgAtoms[b->goal(n).var()];
					Literal lit       = b->goal(n).sign() ? ~pred->literal() : pred->literal();
					if ( (b->goal(n).sign() || pred->scc() != bn->scc) && !ctx.master()->isFalse(lit) ) {
						preds.push_back(lit.asUint());
						if (weights) {
							preds.push_back(b->weight(n));
						}
					}
				}
				preds.push_back(idMax);
			}
		}
		for (HeadVec::const_iterator it = b->heads_begin(), end = b->heads_end(); it != end; ++it) {
			PrgAtomNode* a = prgAtoms[it->node()];
			if (relevantPrgAtom(*ctx.master(), a)) {
				NodeId id = a->ufsNode();
				VarVec::iterator insPos = bn->scc == a->scc() ? succs.begin() : succs.end();
				succs.insert(insPos, id);
			}
		}
		bn->adj_   = new NodeId[succs.size() + bn->extended() + preds.size()];
		if (bn->extended()) {
			*bn->adj_= b->bound();
		}
		bn->sep_   = std::copy(succs.begin(), succs.end(), bn->adj_ + bn->extended());
		std::copy(preds.begin(), preds.end(), bn->sep_);
		ctx.setFrozen(b->var(), true);
	}
	return b->ufsNode();
}
Example #3
0
	void testMiniProject() {
		SharedContext ctx;
		Solver& solver = *ctx.master();
		builder.startProgram(ctx, ProgramBuilder::EqOptions().noEq().noScc())
			.setAtomName(1, "a").setAtomName(2, "b").setAtomName(3, "_x")
			.startRule(CHOICERULE).addHead(1).addHead(2).addHead(3).endRule()
			.startRule().addHead(3).addToBody(1, false).endRule()
			.startRule().addHead(3).addToBody(2, false).endRule()
			.startRule(OPTIMIZERULE).addToBody(3, true).endRule()
		;
		CPPUNIT_ASSERT_EQUAL(true, builder.endProgram());
		std::auto_ptr<BacktrackEnumerator> e(new BacktrackEnumerator(0));
		e->setEnableProjection(true);
		e->enumerate(0);
		MinimizeBuilder b;
		builder.addMinimize(b);
		ctx.addEnumerator(e.release());
		ctx.enumerator()->setMinimize(b.build(ctx));
		ctx.endInit();
		SymbolTable& index = ctx.symTab();
		solver.assume(index[1].lit);
		solver.propagate();
		solver.assume(index[2].lit);
		solver.propagate();
		solver.assume(index[3].lit);
		solver.propagate();
		CPPUNIT_ASSERT(solver.numVars() == solver.numAssignedVars());
		CPPUNIT_ASSERT_EQUAL(Enumerator::enumerate_continue, ctx.enumerator()->backtrackFromModel(solver));
		CPPUNIT_ASSERT(false == solver.propagate());
		solver.backtrack();
		CPPUNIT_ASSERT(false == solver.propagate() && !solver.resolveConflict());
		ctx.detach(solver);
	}
Example #4
0
void ModelEnumerator::addProjectVar(SharedContext& ctx, Var v, bool tag) {
	if (ctx.master()->value(v) == value_free && (!tag || !ctx.marked(posLit(v)))) {
		project_->push_back(v);
		ctx.setFrozen(v, true);
		ctx.setProject(v, true);
		if (tag) { ctx.mark(posLit(v)); ctx.mark(negLit(v)); }
	}
}
Example #5
0
	void testProjectBug() {
		SharedContext ctx;
		Solver& solver = *ctx.master();
		builder.startProgram(ctx, ProgramBuilder::EqOptions().noEq().noScc())
			.setAtomName(1, "x").setAtomName(2, "y").setAtomName(3, "z").setAtomName(4, "_p").setAtomName(5, "_q").setAtomName(6, "_r")
			.startRule(CHOICERULE).addHead(1).addHead(2).addHead(4).endRule() // {x,y,_p}
			.startRule().addHead(5).addToBody(1, true).addToBody(4, true).endRule() // _q :- x,_p.
			.startRule().addHead(6).addToBody(2, true).addToBody(4, true).endRule() // _r :- y,_p.
			.startRule().addHead(3).addToBody(5, true).addToBody(6, true).endRule() // z :- _q,_r.
		;
		CPPUNIT_ASSERT_EQUAL(true, builder.endProgram());
		std::auto_ptr<BacktrackEnumerator> e(new BacktrackEnumerator(7,0));
		e->setEnableProjection(true);
		e->enumerate(0);
		ctx.addEnumerator(e.release());
		ctx.endInit();
		SymbolTable& index = ctx.symTab();
		solver.assume(index[1].lit);
		solver.propagate();
		solver.assume(index[2].lit);
		solver.propagate();
		solver.assume(index[4].lit);
		solver.propagate();
		CPPUNIT_ASSERT(solver.numVars() == solver.numAssignedVars());
		CPPUNIT_ASSERT_EQUAL(Enumerator::enumerate_continue, ctx.enumerator()->backtrackFromModel(solver));

		solver.undoUntil(0);
		uint32 numT = 0;
		if (solver.value(index[1].lit.var()) == value_free) {
			solver.assume(index[1].lit) && solver.propagate();
			++numT;
		}
		else if (solver.isTrue(index[1].lit)) {
			++numT;
		}
		if (solver.value(index[2].lit.var()) == value_free) {
			solver.assume(index[2].lit) && solver.propagate();
			++numT;
		}
		else if (solver.isTrue(index[2].lit)) {
			++numT;
		}
		if (solver.value(index[4].lit.var()) == value_free) {
			solver.assume(index[4].lit) && solver.propagate();
		}
		if (solver.isTrue(index[3].lit)) {
			++numT;
		}
		CPPUNIT_ASSERT(numT < 3);
		ctx.detach(solver);
	}
Example #6
0
	void testParallelRecord() {
		SharedContext ctx; Solver& solver = *ctx.master();
		builder.startProgram(ctx, ProgramBuilder::EqOptions().noEq().noScc())
			.setAtomName(1, "a").setAtomName(2, "b").setAtomName(3, "c").setAtomName(4, "d")
			.startRule(CHOICERULE).addHead(1).addHead(2).addHead(3).addHead(4).endRule()
		;
		CPPUNIT_ASSERT_EQUAL(true, builder.endProgram());
		ctx.setSolvers(2);
		ctx.addEnumerator(new RecordEnumerator(0));
		ctx.enumerator()->enumerate(0);
		ctx.endInit();
		Solver solver2;
		ctx.attach(solver2);
		SymbolTable& index = ctx.symTab();
		solver.assume(index[1].lit) && solver.propagate();
		solver.assume(index[2].lit) && solver.propagate();
		solver.assume(index[3].lit) && solver.propagate();
		solver.assume(index[4].lit) && solver.propagate();
		CPPUNIT_ASSERT_EQUAL(uint32(0), solver.numFreeVars());
		ctx.enumerator()->backtrackFromModel(solver);
		solver.undoUntil(0);
		
		CPPUNIT_ASSERT_EQUAL(true, ctx.enumerator()->update(solver2, false));

		solver2.assume(index[1].lit) && solver2.propagate();
		solver2.assume(index[2].lit) && solver2.propagate();
		solver2.assume(index[3].lit) && solver2.propagate();
		CPPUNIT_ASSERT(solver2.isFalse(index[4].lit) && solver2.propagate());
		CPPUNIT_ASSERT_EQUAL(uint32(0), solver2.numFreeVars());
		ctx.enumerator()->backtrackFromModel(solver2);
		solver.undoUntil(0);

		CPPUNIT_ASSERT_EQUAL(true, ctx.enumerator()->update(solver, false));

		solver.assume(index[1].lit) && solver.propagate();
		solver.assume(index[2].lit) && solver.propagate();
		CPPUNIT_ASSERT(solver.isFalse(index[3].lit));

		ctx.detach(solver2);
		ctx.detach(solver);
		solver2.undoUntil(0);
		ctx.attach(solver2);
		solver2.assume(index[1].lit) && solver2.propagate();
		solver2.assume(index[2].lit) && solver2.propagate();
		solver2.assume(index[3].lit) && solver2.propagate();
		CPPUNIT_ASSERT(solver2.value(index[4].lit.var()) == value_free);
	}
Example #7
0
	void testParallelUpdate() {
		SharedContext ctx; Solver& solver = *ctx.master();
		builder.startProgram(ctx, ProgramBuilder::EqOptions().noEq().noScc())
			.setAtomName(1, "a").setAtomName(2, "b").setAtomName(3, "c")
			.startRule(CHOICERULE).addHead(1).addHead(2).addHead(3).endRule()
			.startRule(OPTIMIZERULE).addToBody(2, true).endRule()
		;
		CPPUNIT_ASSERT_EQUAL(true, builder.endProgram());
		MinimizeBuilder minBuilder;
		builder.addMinimize(minBuilder);
		ctx.setSolvers(2);
		ctx.addEnumerator(new RecordEnumerator(0));
		ctx.enumerator()->enumerate(0);
		ctx.enumerator()->setMinimize(minBuilder.build(ctx));
		ctx.endInit();
		Solver solver2;
		ctx.attach(solver2);
		SymbolTable& index = ctx.symTab();

		// a
		solver.assume(index[1].lit);
		solver.pushRootLevel(1);
		solver.propagate();
		// ~a
		solver2.assume(~index[1].lit);
		solver2.pushRootLevel(1);
		solver2.propagate();

		// M1: ~b, c
		solver.assume(~index[2].lit);
		solver.propagate();
		solver.assume(index[3].lit);
		solver.propagate();	
		CPPUNIT_ASSERT_EQUAL(uint32(0), solver.numFreeVars());
		ctx.enumerator()->backtrackFromModel(solver);
		solver.undoUntil(0);
		
		// M2: ~b, ~c 
		solver2.assume(~index[2].lit);
		solver2.propagate();
		solver2.assume(~index[3].lit);
		solver2.propagate();	
		// M2 is NOT VALID!
		CPPUNIT_ASSERT_EQUAL(false, ctx.enumerator()->update(solver2, true));
	}
Example #8
0
	void testTerminateRemovesWatches() {
		SharedContext ctx; Solver& solver = *ctx.master();
		builder.startProgram(ctx, ProgramBuilder::EqOptions().noEq().noScc())
			.setAtomName(1, "a").setAtomName(2, "b").setAtomName(3, "c").setAtomName(4, "d")
			.startRule(CHOICERULE).addHead(1).addHead(2).addHead(3).addHead(4).endRule()
		;
		CPPUNIT_ASSERT_EQUAL(true, builder.endProgram());
		ctx.addEnumerator(new RecordEnumerator(0));
		ctx.enumerator()->enumerate(0);
		CPPUNIT_ASSERT_EQUAL(true, ctx.endInit());
		
		SymbolTable& index = ctx.symTab();
		solver.assume(index[1].lit) && solver.propagate();
		solver.assume(index[2].lit) && solver.propagate();
		solver.assume(index[3].lit) && solver.propagate();
		solver.assume(index[4].lit) && solver.propagate();
		CPPUNIT_ASSERT_EQUAL(uint32(0), solver.numFreeVars());
		ctx.enumerator()->backtrackFromModel(solver);
		uint32 numW = solver.numWatches(index[1].lit) + solver.numWatches(index[2].lit) + solver.numWatches(index[3].lit) + solver.numWatches(index[4].lit);
		CPPUNIT_ASSERT(numW > 0);
		ctx.detach(solver);
		numW = solver.numWatches(index[1].lit) + solver.numWatches(index[2].lit) + solver.numWatches(index[3].lit) + solver.numWatches(index[4].lit);
		CPPUNIT_ASSERT(numW == 0);
	}
Example #9
0
// Creates a positive-body-atom-dependency graph (PBADG)
// The PBADG contains a node for each atom A of a non-trivial SCC and
// a node for each body B, s.th. there is a non-trivially connected atom A with
// B in body(A).
// Pre : a->ignore  = 0 for all new and relevant atoms a
// Pre : b->visited = 1 for all new and relevant bodies b
// Post: a->ignore  = 1 for all atoms that were added to the PBADG
// Post: b->visited = 0 for all bodies that were added to the PBADG
void SharedDependencyGraph::addSccs(SharedContext& ctx, const AtomList& sccAtoms, const AtomList& prgAtoms, const BodyList& prgBodies) {
	// Pass 1: Create graph atom nodes and estimate number of bodies
	NodeId atomId = static_cast<NodeId>(atoms_.size());
	atoms_.reserve(atoms_.size() + sccAtoms.size());
	AtomList::size_type numBodies = 0;
	for (AtomList::size_type i = 0, end = sccAtoms.size(); i != end; ++i) {
		PrgAtomNode* a = sccAtoms[i];
		if (relevantPrgAtom(*ctx.master(), a)) {
			// initialize graph atom node
			atoms_.push_back(AtomNode());
			AtomNode& ua = atoms_.back();
			ua.lit       = a->literal();
			ua.scc       = a->scc();
			numBodies   += a->preds.size();
			// store link between program node and graph node for later lookup
			a->setUfsNode(atomId, true);
			// atom is defined by more than just a bunch of clauses
			ctx.setFrozen(a->var(), true);
			++atomId;
		}
	}
	// Pass 2: Init atom nodes and create body nodes
	VarVec preds, succs, succsExt;
	NodeId* temp;
	bodies_.reserve(bodies_.size() + numBodies/2);
	for (AtomList::size_type i = 0, end = sccAtoms.size(); i != end; ++i) {
		PrgAtomNode* a = sccAtoms[i];
		if (relevantPrgAtom(*ctx.master(), a)) { 
			AtomNode& ua = atoms_[a->ufsNode()];
			for (HeadVec::const_iterator it = a->preds.begin(), endIt = a->preds.end(); it != endIt; ++it) {
				PrgBodyNode* prgBody = prgBodies[it->node()];
				if (relevantPrgBody(*ctx.master(), prgBody)) {
					NodeId bId = addBody(ctx, prgBody, prgAtoms);
					VarVec::iterator insPos = prgBody->scc() == a->scc() ? preds.end() : preds.begin();
					preds.insert(insPos, bId);
					if (it->choice()) {
						ua.type |= Node::type_in_choice;
					}
				}
			}
			for (VarVec::const_iterator it = a->posDep.begin(), endIt = a->posDep.end(); it != endIt; ++it) {
				PrgBodyNode* prgBody = prgBodies[*it];
				if (prgBody->scc() == a->scc() && relevantPrgBody(*ctx.master(), prgBody)) {
					NodeId bodyId = addBody(ctx, prgBody, prgAtoms);
					if (!bodies_[bodyId].extended()) {
						succs.push_back(bodyId);
					}
					else {
						succsExt.push_back(bodyId);
						succsExt.push_back(bodies_[bodyId].get_pred_idx(a->ufsNode()));
						assert(bodies_[bodyId].get_pred(succsExt.back()) == a->ufsNode());
						ua.type |= Node::type_ext;
					}
				}
			}
			succs.push_back(idMax);
			if (!succsExt.empty()) {
				succsExt.push_back(idMax);
			}
			ua.adj_   = new NodeId[preds.size()+succs.size()+succsExt.size()];
			ua.sep_   = std::copy(preds.begin(), preds.end(), ua.adj_);
			temp      = std::copy(succs.begin(), succs.end(), ua.sep_);
			std::copy(succsExt.begin(), succsExt.end(), temp);
			preds.clear(); succs.clear(); succsExt.clear();
		}
	}	
}