mirror of
https://github.com/Z3Prover/z3
synced 2025-06-27 08:28:44 +00:00
Recognize x != k among new literals in lemma
This commit is contained in:
parent
6715058876
commit
7be82a36f2
4 changed files with 64 additions and 2 deletions
|
@ -237,7 +237,8 @@ namespace polysat {
|
||||||
}
|
}
|
||||||
|
|
||||||
void negate() { m_positive = !m_positive; }
|
void negate() { m_positive = !m_positive; }
|
||||||
signed_constraint operator~() const { return {get(), !is_positive()}; }
|
signed_constraint negated() const { return {get(), !is_positive()}; }
|
||||||
|
signed_constraint operator~() const { return negated(); }
|
||||||
|
|
||||||
bool is_positive() const { return m_positive; }
|
bool is_positive() const { return m_positive; }
|
||||||
bool is_negative() const { return !is_positive(); }
|
bool is_negative() const { return !is_positive(); }
|
||||||
|
@ -268,7 +269,9 @@ namespace polysat {
|
||||||
constraint const& operator*() const { return *m_constraint; }
|
constraint const& operator*() const { return *m_constraint; }
|
||||||
|
|
||||||
bool is_eq() const;
|
bool is_eq() const;
|
||||||
|
bool is_diseq() const { return negated().is_eq(); }
|
||||||
pdd const& eq() const;
|
pdd const& eq() const;
|
||||||
|
pdd const& diseq() const { return negated().eq(); }
|
||||||
|
|
||||||
signed_constraint& operator=(std::nullptr_t) { m_constraint = nullptr; return *this; }
|
signed_constraint& operator=(std::nullptr_t) { m_constraint = nullptr; return *this; }
|
||||||
|
|
||||||
|
|
|
@ -61,11 +61,69 @@ namespace polysat {
|
||||||
{}
|
{}
|
||||||
|
|
||||||
bool simplify_clause::apply(clause& cl) {
|
bool simplify_clause::apply(clause& cl) {
|
||||||
|
if (try_recognize_bailout(cl))
|
||||||
|
return true;
|
||||||
if (try_equal_body_subsumptions(cl))
|
if (try_equal_body_subsumptions(cl))
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If x != k appears among the new literals, all others are superfluous
|
||||||
|
bool simplify_clause::try_recognize_bailout(clause& cl) {
|
||||||
|
LOG_H2("Try to find bailout literal");
|
||||||
|
pvar v = null_var;
|
||||||
|
sat::literal eq = sat::null_literal;
|
||||||
|
rational k;
|
||||||
|
for (sat::literal lit : cl) {
|
||||||
|
LOG_V("Examine " << lit_pp(s, lit));
|
||||||
|
lbool status = s.m_bvars.value(lit);
|
||||||
|
// skip premise literals
|
||||||
|
if (status == l_false)
|
||||||
|
continue;
|
||||||
|
SASSERT(status != l_true); // would be an invalid lemma
|
||||||
|
SASSERT_EQ(status, l_undef); // new literal
|
||||||
|
auto c = s.lit2cnstr(lit);
|
||||||
|
// For now we only handle the case where exactly one variable is
|
||||||
|
// unassigned among the new constraints
|
||||||
|
for (pvar w : c->vars()) {
|
||||||
|
if (s.is_assigned(w))
|
||||||
|
continue;
|
||||||
|
if (v == null_var)
|
||||||
|
v = w;
|
||||||
|
else if (v != w)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
SASSERT(v != null_var); // constraints without unassigned variables would be evaluated at this point
|
||||||
|
if (c.is_diseq() && c.diseq().is_unilinear()) {
|
||||||
|
pdd const& p = c.diseq();
|
||||||
|
if (p.hi().is_one()) {
|
||||||
|
eq = lit;
|
||||||
|
k = (-p.lo()).val();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (eq == sat::null_literal)
|
||||||
|
return false;
|
||||||
|
LOG("Found bailout literal: " << lit_pp(s, eq));
|
||||||
|
// Keep all premise literals and the equation
|
||||||
|
unsigned j = 0;
|
||||||
|
for (unsigned i = 0; i < cl.size(); ++i) {
|
||||||
|
sat::literal const lit = cl[i];
|
||||||
|
lbool const status = s.m_bvars.value(lit);
|
||||||
|
if (status == l_false || lit == eq)
|
||||||
|
cl[j++] = cl[i];
|
||||||
|
else {
|
||||||
|
DEBUG_CODE({
|
||||||
|
auto a = s.assignment();
|
||||||
|
a.push_back({v, k});
|
||||||
|
SASSERT(s.lit2cnstr(lit).is_currently_false(s, a));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cl.m_literals.shrink(j);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract body of the polynomial (i.e., the variable terms without constant term)
|
* Abstract body of the polynomial (i.e., the variable terms without constant term)
|
||||||
* by a single variable.
|
* by a single variable.
|
||||||
|
|
|
@ -29,6 +29,7 @@ namespace polysat {
|
||||||
solver& s;
|
solver& s;
|
||||||
vector<subs_entry> m_entries;
|
vector<subs_entry> m_entries;
|
||||||
|
|
||||||
|
bool try_recognize_bailout(clause& cl);
|
||||||
bool try_equal_body_subsumptions(clause& cl);
|
bool try_equal_body_subsumptions(clause& cl);
|
||||||
|
|
||||||
void prepare_subs_entry(subs_entry& entry, signed_constraint c);
|
void prepare_subs_entry(subs_entry& entry, signed_constraint c);
|
||||||
|
|
|
@ -1408,7 +1408,7 @@ void tst_polysat() {
|
||||||
// test_polysat::test_pop_conflict(); // ok now (had bad conflict/pop interaction)
|
// test_polysat::test_pop_conflict(); // ok now (had bad conflict/pop interaction)
|
||||||
|
|
||||||
// test_polysat::test_l1(); // ok
|
// test_polysat::test_l1(); // ok
|
||||||
// test_polysat::test_l2(); // TODO: loops
|
// test_polysat::test_l2(); // ok but enumerates values
|
||||||
// test_polysat::test_l3(); // ok
|
// test_polysat::test_l3(); // ok
|
||||||
// test_polysat::test_l4(); // ok now (had assertion failure in conflict::insert)
|
// test_polysat::test_l4(); // ok now (had assertion failure in conflict::insert)
|
||||||
// test_polysat::test_l4b(); // ok
|
// test_polysat::test_l4b(); // ok
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue