///////////////////////////////////////////////////////////////////////////////////////// // Lookback selection strategies ///////////////////////////////////////////////////////////////////////////////////////// uint32 momsScore(const Solver& s, Var v) { uint32 sc; if (s.numBinaryConstraints()) { uint32 s1 = s.estimateBCP(posLit(v), 0) - 1; uint32 s2 = s.estimateBCP(negLit(v), 0) - 1; sc = ((s1 * s2)<<10) + (s1 + s2); } else { // problem does not contain binary constraints - fall back to counting watches uint32 s1 = s.numWatches(posLit(v)); uint32 s2 = s.numWatches(negLit(v)); sc = ((s1 * s2)<<10) + (s1 + s2); } return sc; }
void ModelEnumerator::RecordFinder::doCommitModel(Enumerator& x, Solver& s) { ModelEnumerator& ctx = static_cast<ModelEnumerator&>(x); if (ctx.trivial()) { return; } assert(solution.empty() && "Update not called!"); solution.clear(); if (!ctx.projectionEnabled()) { for (uint32 x = s.decisionLevel(); x != 0; --x) { Literal d = s.decision(x); if (!s.auxVar(d.var())) { solution.push_back(~d); } else if (d != s.tagLiteral()) { // Todo: set of vars could be reduced to those having the aux var in their reason set. const LitVec& tr = s.trail(); const uint32 end= x != s.decisionLevel() ? s.levelStart(x+1) : (uint32)tr.size(); for (uint32 n = s.levelStart(x)+1; n != end; ++n) { if (!s.auxVar(tr[n].var())) { solution.push_back(~tr[n]); } } } } } else { for (uint32 i = 0, end = ctx.numProjectionVars(); i != end; ++i) { solution.push_back(~s.trueLit(ctx.projectVar(i))); } } if (queue) { assert(!queue->hasItems(id)); // parallel solving active - share solution nogood with other solvers SL* shared = SL::newShareable(solution, Constraint_t::learnt_other); queue->addSolution(shared, id); solution.clear(); } else if (solution.empty()) { solution.push_back(negLit(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)); } } }
void ClingoPropagator::destroy(Solver* s, bool detach) { if (s && detach) { for (Var v = 1; v <= s->numVars(); ++v) { s->removeWatch(posLit(v), this); s->removeWatch(negLit(v), this); } } destroyDB(db_, s, detach); PostPropagator::destroy(s, detach); }
Literal RestrictedUnit::doSelect(Solver& s) { s.addPost(look_); Literal choice = look_->propagateFixpoint(s) ? look_->heuristic(s) : negLit(0); s.removePost(look_); // if all fld-candidates are currently assigned, use // decorated heuristic to select next choice - // if all vars are assigned after fld, we return posLit(0) // as the "noop" choice. if (choice == posLit(0) && s.numFreeVars() > 0) { choice = default_->doSelect(s); } if (!isSentinel(choice) && --numChoices_ == 0) { destroy(s); } return choice; }
void ModelEnumerator::BacktrackFinder::doCommitModel(Enumerator& ctx, Solver& s) { ModelEnumerator& en = static_cast<ModelEnumerator&>(ctx); uint32 dl = s.decisionLevel(); solution.assign(1, dl ? ~s.decision(dl) : negLit(0)); if (en.projectionEnabled()) { // Remember the current projected assignment as a nogood. solution.clear(); for (uint32 i = 0, end = en.numProjectionVars(); i != end; ++i) { solution.push_back(~s.trueLit(en.projectVar(i))); } // Remember initial decisions that are projection vars. for (dl = s.backtrackLevel(); dl < s.decisionLevel(); ++dl) { if (!s.varInfo(s.decision(dl+1).var()).project()) { break; } } } s.setBacktrackLevel(dl); }
bool CBConsequences::backtrack(Solver& s) { if (C_.empty()) { // no more consequences possible C_.push_back(negLit(0)); } // C_ stores the violated nogood, ie. the new integrity constraint. // C_[0] is the literal assigned on the highest DL and hence the // decision level on which we must analyze the conflict. uint32 newDl = s.level(C_[0].var()); if (getHighestActiveLevel() < newDl) { // C_ is not the most important nogood, ie. there is some other // nogood that is violated below C_. newDl = getHighestActiveLevel() - 1; } s.undoUntil(newDl, true); addNewConstraint(s); return !s.hasConflict() || s.resolveConflict(); }
Literal UnitHeuristic::doSelect(Solver& s) { Literal x = look_->heuristic(s); if (x != posLit(0) || s.numFreeVars() == 0) { return x; } // No candidates. This can happen if the problem // contains choice rules and lookahead is not atom-based. // Add remaining free vars to lookahead so that we can // make an informed decision. VarType types = look_->score.types; for (Var v = 1, end = s.numVars()+1; v != end; ++v) { if ((s.value(v) == value_free || s.level(v) > 0) && (s.sharedContext()->type(v) & types) == 0) { look_->append(s.sharedContext()->preferredLiteralByType(v), true); } } look_->score.clearDeps(); look_->score.types = Var_t::atom_body_var; return look_->propagateFixpoint(s) ? look_->heuristic(s) : negLit(0); }
Literal ClaspBerkmin::selectLiteral(Solver& s, Var var, bool vsids) { Literal l; if ( (l = savedLiteral(s,var)) == posLit(0) ) { int32 w0 = vsids ? (int32)s.estimateBCP(posLit(var), 5) : order_.occ(var); int32 w1 = vsids ? (int32)s.estimateBCP(negLit(var), 5) : 0; if (w1 == 1 && w0 == w1) { // no binary bcp - use occurrences w0 = order_.occ(var); w1 = 0; } return w0 != w1 ? Literal(var, (w0-w1)<0) : s.preferredLiteralByType(var); } else if (order_.huang && (order_.occ(var)*(-1+(2*l.sign()))) > 32) { l = ~l; } return l; }
Literal Lookahead::heuristic(Solver& s) { if (s.value(score.best) != value_free) { // no candidate available return posLit(0); } ScoreLook& sc = score; Literal choice= Literal(sc.best, sc.score[sc.best].prefSign()); if (!sc.deps.empty() && sc.mode == ScoreLook::score_max_min) { // compute heuristic values for candidates skipped during last lookahead uint32 min, max; sc.score[sc.best].score(max, min); sc.addDeps = false; bool ok = true; LitVec::size_type i = 0; do { Var v = sc.deps[i]; VarScore& vs = sc.score[v]; if (s.value(v) == value_free) { uint32 vMin, vMax; vs.score(vMax, vMin); if (vMin == 0 || vMin > min || (vMin == min && vMax > max)) { uint32 neg = vs.score(negLit(v)) > 0 ? vs.score(negLit(v)) : max+1; uint32 pos = vs.score(posLit(v)) > 0 ? vs.score(posLit(v)) : max+1; if (!vs.tested(negLit(v))) { ok = ok && s.test(negLit(v), this); neg = vs.score(negLit(v)); } if ((neg > min || (neg == min && pos > max)) && !vs.tested(posLit(v))) { ok = ok && s.test(posLit(v), this); } } if (vs.testedBoth() && sc.greaterMaxMin(v, max, min)) { vs.score(max, min); choice = Literal(v, vs.prefSign()); } } } while (++i != sc.deps.size() && ok); if (!ok) { // One of the candidates failed. Since none of them failed // during previous propagation, this indicates that // either some post propagator has wrong priority or // parallel solving is active and a stop conflict was set. // Since we can't resolve the problem here, we simply return the // literal that caused the conflict assert(s.hasConflict()); return negLit(0); } } return choice; }