Example #1
0
EnumerationConstraint* ModelEnumerator::doInit(SharedContext& ctx, SharedMinimizeData* opt, int numModels) {
	initProjection(ctx);
	uint32 st = strategy();
	if (detectStrategy() || (ctx.concurrency() > 1 && !ModelEnumerator::supportsParallel())) {
		st = 0;
	}
	bool optOne  = opt && opt->mode() == MinimizeMode_t::optimize;
	bool trivial = optOne || std::abs(numModels) == 1;
	if (optOne && projectionEnabled()) {
		for (const WeightLiteral* it =  minimizer()->lits; !isSentinel(it->first) && trivial; ++it) {
			trivial = ctx.varInfo(it->first.var()).project();
		}
		if (!trivial) { ctx.report(warning(Event::subsystem_prepare, "Projection: Optimization may depend on enumeration order.")); }
	}
	if (st == strategy_auto) { st  = trivial || (projectionEnabled() && ctx.concurrency() > 1) ? strategy_record : strategy_backtrack; }
	if (trivial)             { st |= trivial_flag; }
	options_ &= ~uint32(strategy_opts_mask);
	options_ |= st;
	const LitVec* dom = (projectOpts() & project_dom_lits) != 0 ? (ctx.heuristic.domRec = &domRec_) : 0;
	EnumerationConstraint* c = st == strategy_backtrack
	  ? static_cast<ConPtr>(new BacktrackFinder(projectOpts()))
	  : static_cast<ConPtr>(new RecordFinder(dom));
	if (projectionEnabled()) { setIgnoreSymmetric(true); }
	return c;
}
Example #2
0
EnumerationConstraint* ModelEnumerator::doInit(SharedContext& ctx, MinimizeConstraint* min, int numModels) {
	delete queue_;
	queue_ = 0;
	initProjection(ctx); 
	uint32 st = strategy();
	if (detectStrategy() || (ctx.concurrency() > 1 && !ModelEnumerator::supportsParallel())) {
		st = 0;
	}
	bool optOne  = minimizer() && minimizer()->mode() == MinimizeMode_t::optimize;
	bool trivial = optOne || std::abs(numModels) == 1;
	if (optOne && project_) {
		const SharedMinimizeData* min = minimizer();
		for (const WeightLiteral* it = min->lits; !isSentinel(it->first) && trivial; ++it) {
			trivial = ctx.varInfo(it->first.var()).project();
		}
		if (!trivial) { ctx.report(warning(Event::subsystem_prepare, "Projection: Optimization may depend on enumeration order.")); }
	}
	if (st == strategy_auto) { st  = trivial || (project_ && ctx.concurrency() > 1) ? strategy_record : strategy_backtrack; }
	if (trivial)             { st |= trivial_flag; }
	if (ctx.concurrency() > 1 && !trivial && st != strategy_backtrack) {
		queue_ = new SolutionQueue(ctx.concurrency()); 
		queue_->reserve(ctx.concurrency() + 1);
	}
	options_ &= ~uint32(strategy_opts_mask);
	options_ |= st;
	Solver& s = *ctx.master();
	EnumerationConstraint* c = st == strategy_backtrack 
	  ? static_cast<ConPtr>(new BacktrackFinder(s, min, project_, projectOpts()))
	  : static_cast<ConPtr>(new RecordFinder(s, min, project_, queue_));
	if (projectionEnabled()) { setIgnoreSymmetric(true); }
	return c;
}
Example #3
0
bool RecordEnumerator::doBacktrack(Solver& s, uint32 bl) {
	assert(bl >= s.rootLevel());
	if (!projectionEnabled()) {
		addSolution(s);
	}
	bl = std::min(bl, assertionLevel(s));
	if (s.backtrackLevel() > 0) {
		// must clear backtracking level;
		// not needed to guarantee redundancy-freeness
		// and may inadvertently bound undoUntil()
		s.setBacktrackLevel(0);
	}
	s.undoUntil(bl);
	if (solution_.empty()) {
		assert(minimize() && minimize()->mode() == MinimizeConstraint::compare_less);
		return true;
	}
	bool r = true;
	if (solution_.size() < 4) {
		r = solution_.end();
	}
	else {
		Literal x;
		if (s.isFalse(solution_[solution_.secondWatch()])) {
			x = solution_[0];
		}
		LearntConstraint* c = Clause::newLearntClause(s, solution_.lits(), Constraint_t::learnt_conflict, solution_.secondWatch());
		nogoods_.push_back((Clause*)c);
		r = s.force(x, c);
	}
	return r || s.resolveConflict();
}
Example #4
0
bool ModelEnumerator::backtrack(Solver& s) {
	uint32 bl = getHighestActiveLevel();
	if (projectionEnabled()) {
		bl = std::min(bl, getProjectLevel(s));
	}
	if (bl <= s.rootLevel()) {
		return false;
	}
	return doBacktrack(s, bl-1);
}
Example #5
0
uint32 BacktrackEnumerator::getHighestBacktrackLevel(const Solver& s, uint32 bl) const {
	if (!projectionEnabled() || (projectOpts_ & MINIMIZE_BACKJUMPING) == 0) {
		return s.backtrackLevel();
	}
	uint32 res = s.backtrackLevel();
	for (uint32 r = res+1; r <= bl; ++r) {
		if (!s.project(s.decision(r).var())) {
			return res;
		}
		++res;
	}
	return res;
}
Example #6
0
void ModelEnumerator::initProjection(SharedContext& ctx) {
	if (!projectionEnabled()) { return; }
	const OutputTable& out = ctx.output;
	char const filter = static_cast<char>(options_ >> 24);
	// Make sure that nogoods are tagged with step literal.
	addProject(ctx, ctx.stepLiteral().var());
	if (out.projectMode() == OutputTable::project_output) {
		// Mark all relevant output variables.
		for (OutputTable::pred_iterator it = out.pred_begin(), end = out.pred_end(); it != end; ++it) {
			if (*it->name != filter) { addProject(ctx, it->cond.var()); }
		}
		for (OutputTable::range_iterator it = out.vars_begin(), end = out.vars_end(); it != end; ++it) {
			for (Var v = it->lo; v != it->hi; ++v) { addProject(ctx, v); }
		}
	}
	else {
		// Mark explicitly requested variables only.
		for (OutputTable::lit_iterator it = out.proj_begin(), end = out.proj_end(); it != end; ++it) {
			addProject(ctx, it->var());
		}
	}
	domRec_.clear();
}
Example #7
0
bool ModelEnumerator::ignoreSymmetric() const {
	return projectionEnabled() || Enumerator::ignoreSymmetric();
}
Example #8
0
bool BacktrackEnumerator::doBacktrack(Solver& s, uint32 bl) {
	// bl is the decision level on which search should proceed.
	// bl + 1 the minimum of:
	//  a) the highest DL on which one of the projected vars was assigned
	//  b) the highest DL on which one of the vars in a minimize statement was assigned
	//  c) the current decision level
	assert(bl >= s.rootLevel());
	++bl; 
	assert(bl <= s.decisionLevel());
	uint32 btLevel = getHighestBacktrackLevel(s, bl);
	if (!projectionEnabled() || bl <= btLevel) {
		// If we do not project or one of the projection vars is already on the backtracking level
		// proceed with simple backtracking.
		while (!s.backtrack() || s.decisionLevel() >= bl) {
			if (s.decisionLevel() == s.rootLevel()) {
				return false;
			}
		}
		return true;
	}
	else if (numProjectionVars() == 1u) {
		Literal x = s.trueLit(projectVar(0));
		s.undoUntil(0);
		s.force(~x, 0); // force the complement of x
		s.setBacktrackLevel(s.decisionLevel());
	}
	else {
		// Store the current projected assignment as a nogood
		// and attach it to the current decision level.
		// Once the solver goes above that level, the nogood is automatically
		// destroyed. Hence, the number of projection nogoods is linear in the
		// number of (projection) atoms.
		if ( (projectOpts_ & ENABLE_PROGRESS_SAVING) != 0 ) {
			s.strategies().saveProgress = 1;
		}
		projAssign_.clear();
		projAssign_.resize(numProjectionVars());
		LitVec::size_type front = 0;
		LitVec::size_type back  = numProjectionVars();
		for (uint32 i = 0; i != numProjectionVars(); ++i) {
			Literal x = ~s.trueLit(projectVar(i)); // Note: complement because we store the nogood as a clause!
			if (s.level(x.var()) > btLevel) {
				projAssign_[front++] = x;
			}
			else {
				projAssign_[--back] = x;
			}
		}
		s.undoUntil( btLevel );
		Literal x = projAssign_[0];
		LearntConstraint* c;
		if (front == 1) {
			// The projection nogood is unit. Force the single remaining literal
			// from the current DL. 
			++back; // so that the active part of the nogood contains at least two literals
			c = Clause::newContractedClause(s, projAssign_, back-1, back);
			s.force(x, c);
		}
		else {
			// Shorten the projection nogood by assuming one of its literals...
			if ( (projectOpts_ & ENABLE_HEURISTIC_SELECT) != 0 ) {
				x = s.strategies().heuristic->selectRange(s, &projAssign_[0], &projAssign_[0]+back);
			}
			c = Clause::newContractedClause(s, projAssign_, back-1, back);
			// to false.
			s.assume(~x);
		}
		if (s.backtrackLevel() < s.decisionLevel()) {
			// Remember that we must backtrack the current decision
			// level in order to guarantee a different projected solution.
			s.setBacktrackLevel(s.decisionLevel());
		}
		if (s.decisionLevel() != 0) {
			// Attach nogood to the current decision literal. 
			// Once the solver goes above that level, the nogood (which is then satisfied) is destroyed.
			s.addUndoWatch(s.decisionLevel(), this);
		}
		nogoods_.push_back( NogoodPair(c, s.decisionLevel()) );
		assert(s.backtrackLevel() == s.decisionLevel());
	}
	return true;
}