3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-30 20:35:51 +00:00

Polysat: use constraint_literal and begin move to core-based conflict representation (#5489)

* Rename solver_scope for fixplex tests

(otherwise the wrong constructor is called for polysat's solver_scope)

* Update conflict_core

* simplify

* Be clearer about constraint_literal lifetime

* remove old comment

* Remove status (positive/negative) from constraint

* Use constraint_literal in the solver

* Fix build (constraint -> get_constraint)
This commit is contained in:
Jakob Rath 2021-08-18 20:02:46 +02:00 committed by GitHub
parent 30e9f24fa3
commit ebaea2159e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 933 additions and 1004 deletions

View file

@ -18,82 +18,73 @@ Author:
namespace polysat {
std::ostream& eq_constraint::display(std::ostream& out) const {
out << p() << " == 0";
return display_extra(out);
std::ostream& eq_constraint::display(std::ostream& out, lbool status) const {
out << p();
if (status == l_true) out << " == 0";
else if (status == l_false) out << " != 0";
else out << " ==/!= 0";
return display_extra(out, status);
}
void eq_constraint::narrow(solver& s) {
SASSERT(!is_undef());
void eq_constraint::narrow(solver& s, bool is_positive) {
LOG("Assignment: " << assignments_pp(s));
auto q = p().subst_val(s.assignment());
LOG("Substituted: " << p() << " := " << q);
if (q.is_zero()) {
if (is_positive())
return;
if (is_negative()) {
if (!is_positive) {
LOG("Conflict (zero under current assignment)");
s.set_conflict(*this);
return;
s.set_conflict({this, is_positive});
}
return;
}
if (q.is_never_zero()) {
if (is_positive()) {
if (is_positive) {
LOG("Conflict (never zero under current assignment)");
s.set_conflict(*this);
return;
s.set_conflict({this, is_positive});
}
if (is_negative())
return;
return;
}
if (q.is_unilinear()) {
// a*x + b == 0
pvar v = q.var();
s.push_cjust(v, this);
s.push_cjust(v, {this, is_positive});
rational a = q.hi().val();
rational b = q.lo().val();
s.m_viable.intersect_eq(a, v, b, is_positive());
s.m_viable.intersect_eq(a, v, b, is_positive);
rational val;
if (s.m_viable.find_viable(v, val) == dd::find_t::singleton)
s.propagate(v, val, *this);
s.propagate(v, val, {this, is_positive});
return;
}
// TODO: what other constraints can be extracted cheaply?
}
bool eq_constraint::is_always_false() {
if (is_positive())
bool eq_constraint::is_always_false(bool is_positive) {
if (is_positive)
return p().is_never_zero();
if (is_negative())
else
return p().is_zero();
UNREACHABLE();
return false;
}
bool eq_constraint::is_currently_false(solver& s) {
bool eq_constraint::is_currently_false(solver& s, bool is_positive) {
pdd r = p().subst_val(s.assignment());
if (is_positive())
if (is_positive)
return r.is_never_zero();
if (is_negative())
else
return r.is_zero();
UNREACHABLE();
return false;
}
bool eq_constraint::is_currently_true(solver& s) {
bool eq_constraint::is_currently_true(solver& s, bool is_positive) {
pdd r = p().subst_val(s.assignment());
if (is_positive())
if (is_positive)
return r.is_zero();
if (is_negative())
else
return r.is_never_zero();
UNREACHABLE();
return false;
}
@ -130,10 +121,8 @@ namespace polysat {
/// Compute forbidden interval for equality constraint by considering it as p <=u 0 (or p >u 0 for disequality)
bool eq_constraint::forbidden_interval(solver& s, pvar v, eval_interval& out_interval, constraint_literal& out_neg_cond)
bool eq_constraint::forbidden_interval(solver& s, bool is_positive, pvar v, eval_interval& out_interval, constraint_literal_ref& out_neg_cond)
{
SASSERT(!is_undef());
// Current only works when degree(v) is at most one
unsigned const deg = p().degree(v);
if (deg > 1)
@ -182,7 +171,7 @@ namespace polysat {
rational lo_val = (1 - e1s).val();
pdd hi = -e1;
rational hi_val = (-e1s).val();
if (is_negative()) {
if (!is_positive) {
swap(lo, hi);
lo_val.swap(hi_val);
}
@ -191,10 +180,9 @@ namespace polysat {
return true;
}
inequality eq_constraint::as_inequality() const {
SASSERT(!is_undef());
inequality eq_constraint::as_inequality(bool is_positive) const {
pdd zero = p() - p();
if (is_positive())
if (is_positive)
// p <= 0
return inequality(p(), zero, false, this);
else