// Backward subsumption + backward subsumption resolution bool SimpSolver::backwardSubsumptionCheck(bool verbose) { int cnt = 0; int subsumed = 0; int deleted_literals = 0; assert(decisionLevel() == 0); while (subsumption_queue.size() > 0 || bwdsub_assigns < trail.size()){ // Check top-level assignments by creating a dummy clause and placing it in the queue: if (subsumption_queue.size() == 0 && bwdsub_assigns < trail.size()){ Lit l = trail[bwdsub_assigns++]; (*bwdsub_tmpunit)[0] = l; bwdsub_tmpunit->calcAbstraction(); assert(bwdsub_tmpunit->mark() == 0); subsumption_queue.insert(bwdsub_tmpunit); } Clause& c = *subsumption_queue.peek(); subsumption_queue.pop(); if (c.mark()) continue; if (verbose && verbosity >= 2 && cnt++ % 1000 == 0) reportf("subsumption left: %10d (%10d subsumed, %10d deleted literals)\r", subsumption_queue.size(), subsumed, deleted_literals); assert(c.size() > 1 || value(c[0]) == l_True); // Unit-clauses should have been propagated before this point. // Find best variable to scan: Var best = var(c[0]); for (int i = 1; i < c.size(); i++) if (occurs[var(c[i])].size() < occurs[best].size()) best = var(c[i]); // Search all candidates: vec<Clause*>& _cs = getOccurs(best); Clause** cs = (Clause**)_cs; for (int j = 0; j < _cs.size(); j++) if (c.mark()) break; else if (!cs[j]->mark() && cs[j] != &c){ Lit l = c.subsumes(*cs[j]); if (l == lit_Undef) subsumed++, removeClause(*cs[j]); else if (l != lit_Error){ deleted_literals++; if (!strengthenClause(*cs[j], ~l)) return false; // Did current candidate get deleted from cs? Then check candidate at index j again: if (var(l) == best) j--; } } } return true; }
bool SimpSMTSolver::eliminateVar(Var v, bool fail) { if (!fail && asymm_mode && !asymmVar(v)) return false; const vec<Clause*>& cls = getOccurs(v); // if (value(v) != l_Undef || cls.size() == 0) return true; if (value(v) != l_Undef) return true; // Split the occurrences into positive and negative: vec<Clause*> pos, neg; for (int i = 0; i < cls.size(); i++) (find(*cls[i], Lit(v)) ? pos : neg).push(cls[i]); // Check if number of clauses decreases: int cnt = 0; for (int i = 0; i < pos.size(); i++) for (int j = 0; j < neg.size(); j++) if (merge(*pos[i], *neg[j], v) && ++cnt > cls.size() + grow) return true; #ifdef PEDANTIC_DEBUG cerr << "XXY gonna-remove" << endl; #endif // Delete and store old clauses: setDecisionVar(v, false); elimtable[v].order = elimorder++; assert(elimtable[v].eliminated.size() == 0); for (int i = 0; i < cls.size(); i++) { elimtable[v].eliminated.push(Clause_new(*cls[i])); removeClause(*cls[i]); } // Produce clauses in cross product: int top = clauses.size(); vec<Lit> resolvent; for (int i = 0; i < pos.size(); i++) for (int j = 0; j < neg.size(); j++) if (merge(*pos[i], *neg[j], v, resolvent) && !addClause(resolvent)) return false; // DEBUG: For checking that a clause set is saturated with respect to variable elimination. // If the clause set is expected to be saturated at this point, this constitutes an // error. if (fail){ reportf("eliminated var %d, %d <= %d\n", v+1, cnt, cls.size()); reportf("previous clauses:\n"); for (int i = 0; i < cls.size(); i++){ printClause(*cls[i]); reportf("\n"); } reportf("new clauses:\n"); for (int i = top; i < clauses.size(); i++){ printClause(*clauses[i]); reportf("\n"); } assert(0); } return backwardSubsumptionCheck(); }
bool SimpSolver::asymmVar(Var v) { assert(!frozen[v]); assert(use_simplification); vec<Clause*> pos, neg; const vec<Clause*>& cls = getOccurs(v); if (value(v) != l_Undef || cls.size() == 0) return true; for (int i = 0; i < cls.size(); i++) if (!asymm(v, *cls[i])) return false; return backwardSubsumptionCheck(); }
void SimpSolver::gatherTouchedClauses() { //fprintf(stderr, "Gathering clauses for backwards subsumption\n"); int ntouched = 0; for (int i = 0; i < touched.size(); i++) if (touched[i]){ const vec<Clause*>& cs = getOccurs(i); ntouched++; for (int j = 0; j < cs.size(); j++) if (cs[j]->mark() == 0){ subsumption_queue.insert(cs[j]); cs[j]->mark(2); } touched[i] = 0; } //fprintf(stderr, "Touched variables %d of %d yields %d clauses to check\n", ntouched, touched.size(), clauses.size()); for (int i = 0; i < subsumption_queue.size(); i++) subsumption_queue[i]->mark(0); }