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(); }
bool SimpSolver::eliminate(bool turn_off_elim) { if (!ok || !use_simplification) return ok; // Main simplification loop: //assert(subsumption_queue.size() == 0); //gatherTouchedClauses(); while (subsumption_queue.size() > 0 || elim_heap.size() > 0){ //fprintf(stderr, "subsumption phase: (%d)\n", subsumption_queue.size()); if (!backwardSubsumptionCheck(true)) return false; //fprintf(stderr, "elimination phase:\n (%d)", elim_heap.size()); for (int cnt = 0; !elim_heap.empty(); cnt++){ Var elim = elim_heap.removeMin(); if (verbosity >= 2 && cnt % 100 == 0) reportf("elimination left: %10d\r", elim_heap.size()); if (!frozen[elim] && !eliminateVar(elim)) return false; } assert(subsumption_queue.size() == 0); gatherTouchedClauses(); } // Cleanup: cleanUpClauses(); order_heap.filter(VarFilter(*this)); #ifdef INVARIANTS // Check that no more subsumption is possible: reportf("Checking that no more subsumption is possible\n"); for (int i = 0; i < clauses.size(); i++){ if (i % 1000 == 0) reportf("left %10d\r", clauses.size() - i); assert(clauses[i]->mark() == 0); for (int j = 0; j < i; j++) assert(clauses[i]->subsumes(*clauses[j]) == lit_Error); } reportf("done.\n"); // Check that no more elimination is possible: reportf("Checking that no more elimination is possible\n"); for (int i = 0; i < nVars(); i++) if (!frozen[i]) eliminateVar(i, true); reportf("done.\n"); checkLiteralCount(); #endif // If no more simplification is needed, free all simplification-related data structures: if (turn_off_elim){ use_simplification = false; touched.clear(true); occurs.clear(true); n_occ.clear(true); subsumption_queue.clear(true); elim_heap.clear(true); remove_satisfied = true; } return true; }