3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-08-22 19:17:53 +00:00

We need more clause names

This commit is contained in:
Jakob Rath 2023-02-03 15:51:53 +01:00
parent bdf20f513b
commit 5678c1c592
5 changed files with 42 additions and 26 deletions

View file

@ -22,19 +22,23 @@ namespace polysat {
static_assert(std::is_move_assignable_v<clause_builder>); static_assert(std::is_move_assignable_v<clause_builder>);
static_assert(std::is_move_constructible_v<clause_builder>); static_assert(std::is_move_constructible_v<clause_builder>);
clause_builder::clause_builder(solver& s): clause_builder::clause_builder(solver& s, char const* name):
m_solver(&s) m_solver(&s), m_name(name)
{} {}
void clause_builder::reset() { void clause_builder::reset() {
m_literals.reset(); m_literals.reset();
m_is_tautology = false; m_is_tautology = false;
m_redundant = clause::redundant_default; m_redundant = clause::redundant_default;
m_name = "";
SASSERT(empty()); SASSERT(empty());
} }
clause_ref clause_builder::build() { clause_ref clause_builder::build() {
if (m_is_tautology) { if (m_is_tautology) {
verbose_stream() << "Tautology: " << m_literals << " (" << (m_name ? m_name : "<null>") << ")\n";
for (sat::literal lit : m_literals)
verbose_stream() << " " << lit_pp(*m_solver, lit) << "\n";
reset(); reset();
return nullptr; return nullptr;
} }
@ -52,7 +56,9 @@ namespace polysat {
clause_ref cl = clause::from_literals(std::move(m_literals)); clause_ref cl = clause::from_literals(std::move(m_literals));
SASSERT(cl); SASSERT(cl);
cl->set_redundant(m_redundant); cl->set_redundant(m_redundant);
cl->set_name(m_name);
m_redundant = clause::redundant_default; m_redundant = clause::redundant_default;
m_name = "";
SASSERT(empty()); SASSERT(empty());
return cl; return cl;
} }

View file

@ -29,24 +29,26 @@ namespace polysat {
/// (only this specific case of tautology is covered by this flag) /// (only this specific case of tautology is covered by this flag)
bool m_is_tautology = false; bool m_is_tautology = false;
bool m_redundant = clause::redundant_default; bool m_redundant = clause::redundant_default;
char const* m_name;
solver& s() const { return *m_solver; } solver& s() const { return *m_solver; }
public: public:
clause_builder(solver& s); clause_builder(solver& s, char const* name = "");
clause_builder(clause_builder const& s) = delete; clause_builder(clause_builder const&) = delete;
clause_builder(clause_builder&& s) = default; clause_builder(clause_builder&&) = default;
clause_builder& operator=(clause_builder const& s) = delete; clause_builder& operator=(clause_builder const&) = delete;
clause_builder& operator=(clause_builder&& s) = default; clause_builder& operator=(clause_builder&&) = default;
bool empty() const { return m_literals.empty() && !m_is_tautology && m_redundant == clause::redundant_default; } bool empty() const { return m_literals.empty() && !m_is_tautology && m_redundant == clause::redundant_default; }
void reset(); void reset();
void set_redundant(bool r) { m_redundant = r; } void set_redundant(bool r) { m_redundant = r; }
void set_name(char const* name) { m_name = name; }
/// Build the clause. This will reset the clause builder so it can be reused. /// Build the clause. This will reset the clause builder so it can be reused.
/// Returns nullptr if the clause is a tautology and should not be added to the solver. /// Returns nullptr if the clause is a tautology and should not be added to the solver.
clause_ref build(); [[nodiscard]] clause_ref build();
/// Insert constraints into the clause. /// Insert constraints into the clause.
void insert(sat::literal lit); void insert(sat::literal lit);

View file

@ -1121,6 +1121,11 @@ namespace polysat {
} }
} }
void solver::add_clause(clause_ref clause) {
VERIFY(clause);
add_clause(*clause);
}
// Add clause to solver // Add clause to solver
void solver::add_clause(clause& clause) { void solver::add_clause(clause& clause) {
LOG((clause.is_redundant() ? "Lemma: ": "Aux: ") << clause); LOG((clause.is_redundant() ? "Lemma: ": "Aux: ") << clause);

View file

@ -290,6 +290,7 @@ namespace polysat {
void learn_lemma(clause& lemma); void learn_lemma(clause& lemma);
void backjump(unsigned new_level); void backjump(unsigned new_level);
void add_clause(clause_ref clause);
void add_clause(clause& clause); void add_clause(clause& clause);
void add_clause(signed_constraint c1, bool is_redundant); void add_clause(signed_constraint c1, bool is_redundant);
void add_clause(signed_constraint c1, signed_constraint c2, bool is_redundant); void add_clause(signed_constraint c1, signed_constraint c2, bool is_redundant);

View file

@ -117,6 +117,8 @@ namespace polysat {
auto const& max = p.manager().max_value(); auto const& max = p.manager().max_value();
// p * q >= max + 1 <=> q >= (max + 1)/p <=> q >= ceil((max+1)/p) // p * q >= max + 1 <=> q >= (max + 1)/p <=> q >= ceil((max+1)/p)
auto bound = ceil((max + 1) / p.val()); auto bound = ceil((max + 1) / p.val());
SASSERT(bound * p.val() > max);
SASSERT((bound - 1) * p.val() <= max);
// //
// the clause that explains bound <= q or bound > q // the clause that explains bound <= q or bound > q
@ -126,20 +128,20 @@ namespace polysat {
// //
signed_constraint sc(this, is_positive); signed_constraint sc(this, is_positive);
signed_constraint premise = is_positive ? s.ule(p0, p.val()) : s.ule(p.val(), p0); if (is_positive) {
signed_constraint conseq = is_positive ? s.ule(bound, q0) : s.ult(q0, bound); clause_builder lemma(s, "Ovfl(p, q) & p <= p.val() ==> q >= bound");
lemma.insert_eval(~sc);
SASSERT(premise.is_currently_true(s)); lemma.insert_eval(~s.ule(p0, p.val()));
SASSERT(bound * p.val() > max); lemma.insert(s.ule(bound, q0));
SASSERT((bound - 1) * p.val() <= max); s.add_clause(lemma.build());
clause_builder cb(s); }
cb.insert_eval(~sc); else {
cb.insert_eval(~premise); clause_builder lemma(s, "~Ovfl(p, q) & p >= p.val() ==> q < bound");
cb.insert(conseq); lemma.insert_eval(~sc);
clause_ref just = cb.build(); lemma.insert_eval(~s.ule(p.val(), p0));
SASSERT(just); lemma.insert(s.ult(q0, bound));
s.add_clause(*just); s.add_clause(lemma.build());
SASSERT(s.m_bvars.is_true(conseq.blit())); }
return true; return true;
} }