3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-05-07 07:45:46 +00:00

Polysat disjunctive lemmas (WIP) (#5275)

* Extend search state by boolean literals

* Only resolve against positive equality

* mk_dep_ref

* Make clause non-owning

* scoped_clause

* Use scoped_clause

* minor

* scoped_ptr move assignment

* WIP: internal handling of disjunctive constraints

* leaf_value

* disjunctive constraints continued

* Fix bool_lit

* Actually add constraints to storage

* Some fixes

* more fixes

* constraint should have a bool_lit instead of a bool_var

* propagate(bool_lit)

* updates

* interface changes

* small fixes

* Make sat::dimacs_lit's constructor explicit

(otherwise, calling operator<< with sat::literal is ambiguous)

* Use sat::literal

* Print test name at the beginning

* Convention: constraint corresponds to the positive boolean literal

* Make constraint ownership more explicit

* clause stores literals
This commit is contained in:
Jakob Rath 2021-05-21 22:50:25 +02:00 committed by GitHub
parent 49e9782238
commit 28996429df
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
24 changed files with 1196 additions and 360 deletions

View file

@ -21,6 +21,45 @@ Author:
namespace polysat {
constraint* constraint_manager::insert(scoped_ptr<constraint>&& sc) {
constraint* c = sc.detach();
LOG_V("Inserting constraint: " << show_deref(c));
SASSERT(c);
SASSERT(c->bvar() != sat::null_bool_var);
SASSERT(get_bv2c(c->bvar()) == nullptr);
insert_bv2c(c->bvar(), c);
// TODO: use explicit insert_external(constraint* c, unsigned dep) for that.
if (c->dep() && c->dep()->is_leaf()) {
unsigned dep = c->dep()->leaf_value();
SASSERT(!m_external_constraints.contains(dep));
m_external_constraints.insert(dep, c);
}
while (m_constraints.size() <= c->level())
m_constraints.push_back({});
m_constraints[c->level()].push_back(c);
return c;
}
// Release constraints at the given level and above.
void constraint_manager::release_level(unsigned lvl) {
for (unsigned l = m_constraints.size(); l-- > lvl; ) {
for (constraint* c : m_constraints[l]) {
LOG_V("Removing constraint: " << show_deref(c));
erase_bv2c(c->bvar());
if (c->dep() && c->dep()->is_leaf()) {
unsigned dep = c->dep()->leaf_value();
SASSERT(m_external_constraints.contains(dep));
m_external_constraints.remove(dep);
}
}
m_constraints[l].reset();
}
}
constraint* constraint_manager::lookup(sat::bool_var var) const {
return get_bv2c(var);
}
eq_constraint& constraint::to_eq() {
return *dynamic_cast<eq_constraint*>(this);
}
@ -45,19 +84,22 @@ namespace polysat {
return *dynamic_cast<var_constraint const*>(this);
}
constraint* constraint::eq(unsigned lvl, bool_var bvar, csign_t sign, pdd const& p, p_dependency_ref const& d) {
return alloc(eq_constraint, lvl, bvar, sign, p, d);
scoped_ptr<constraint> constraint_manager::eq(unsigned lvl, csign_t sign, pdd const& p, p_dependency_ref const& d) {
return alloc(eq_constraint, *this, lvl, sign, p, d);
}
constraint* constraint::viable(unsigned lvl, bool_var bvar, csign_t sign, pvar v, bdd const& b, p_dependency_ref const& d) {
return alloc(var_constraint, lvl, bvar, sign, v, b, d);
scoped_ptr<constraint> constraint_manager::viable(unsigned lvl, csign_t sign, pvar v, bdd const& b, p_dependency_ref const& d) {
return alloc(var_constraint, *this, lvl, sign, v, b, d);
}
constraint* constraint::ule(unsigned lvl, bool_var bvar, csign_t sign, pdd const& a, pdd const& b, p_dependency_ref const& d) {
return alloc(ule_constraint, lvl, bvar, sign, a, b, d);
scoped_ptr<constraint> constraint_manager::ule(unsigned lvl, csign_t sign, pdd const& a, pdd const& b, p_dependency_ref const& d) {
return alloc(ule_constraint, *this, lvl, sign, a, b, d);
}
scoped_ptr<constraint> constraint_manager::ult(unsigned lvl, csign_t sign, pdd const& a, pdd const& b, p_dependency_ref const& d) {
// a < b <=> !(b <= a)
return ule(lvl, static_cast<csign_t>(!sign), b, a, d);
}
// To do signed comparison of bitvectors, flip the msb and do unsigned comparison:
//
@ -75,19 +117,14 @@ namespace polysat {
//
// Argument: flipping the msb swaps the negative and non-negative blocks
//
constraint* constraint::sle(unsigned lvl, bool_var bvar, csign_t sign, pdd const& a, pdd const& b, p_dependency_ref const& d) {
scoped_ptr<constraint> constraint_manager::sle(unsigned lvl, csign_t sign, pdd const& a, pdd const& b, p_dependency_ref const& d) {
auto shift = rational::power_of_two(a.power_of_2() - 1);
return ule(lvl, bvar, sign, a + shift, b + shift, d);
return ule(lvl, sign, a + shift, b + shift, d);
}
constraint* constraint::slt(unsigned lvl, bool_var bvar, csign_t sign, pdd const& a, pdd const& b, p_dependency_ref const& d) {
scoped_ptr<constraint> constraint_manager::slt(unsigned lvl, csign_t sign, pdd const& a, pdd const& b, p_dependency_ref const& d) {
auto shift = rational::power_of_two(a.power_of_2() - 1);
return ult(lvl, bvar, sign, a + shift, b + shift, d);
}
constraint* constraint::ult(unsigned lvl, bool_var bvar, csign_t sign, pdd const& a, pdd const& b, p_dependency_ref const& d) {
// a < b <=> !(b <= a)
return ule(lvl, bvar, static_cast<csign_t>(!sign), b, a, d);
return ult(lvl, sign, a + shift, b + shift, d);
}
bool constraint::propagate(solver& s, pvar v) {
@ -118,4 +155,66 @@ namespace polysat {
narrow(s);
}
clause* clause::from_literals(unsigned lvl, p_dependency_ref const& d, sat::literal_vector const& literals) {
return alloc(clause, lvl, d, literals);
}
bool clause::is_always_false(solver& s) const {
return std::all_of(m_literals.begin(), m_literals.end(), [&s](sat::literal lit) {
constraint *c = s.m_constraints.lookup(lit.var());
return c->is_always_false();
});
}
bool clause::is_currently_false(solver& s) const {
return std::all_of(m_literals.begin(), m_literals.end(), [&s](sat::literal lit) {
constraint *c = s.m_constraints.lookup(lit.var());
return c->is_currently_false(s);
});
}
std::ostream& clause::display(std::ostream& out) const {
bool first = true;
for (auto lit : literals()) {
if (first)
first = false;
else
out << " \\/ ";
out << lit;
}
return out;
}
scoped_clause::scoped_clause(scoped_ptr<constraint>&& c) {
SASSERT(c);
sat::literal_vector lits;
lits.push_back(sat::literal(c->bvar()));
m_clause = clause::from_literals(c->level(), c->m_dep, lits);
m_owned.push_back(c.detach());
}
std::ostream& scoped_clause::display(std::ostream& out) const {
if (m_clause)
return out << *m_clause;
else
return out << "<NULL>";
}
std::ostream& constraints_and_clauses::display(std::ostream& out) const {
bool first = true;
for (auto* c : units()) {
if (first)
first = false;
else
out << " ; ";
out << show_deref(c);
}
for (auto* cl : clauses()) {
if (first)
first = false;
else
out << " ; ";
out << show_deref(cl);
}
return out;
}
}