mirror of
https://github.com/Z3Prover/z3
synced 2025-04-30 12:25:51 +00:00
108 lines
2.9 KiB
C++
108 lines
2.9 KiB
C++
/*++
|
|
Copyright (c) 2021 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
polysat eq_constraints
|
|
|
|
Author:
|
|
|
|
Nikolaj Bjorner (nbjorner) 2021-03-19
|
|
Jakob Rath 2021-04-6
|
|
|
|
--*/
|
|
|
|
#include "math/polysat/constraint.h"
|
|
#include "math/polysat/solver.h"
|
|
#include "math/polysat/log.h"
|
|
|
|
namespace polysat {
|
|
|
|
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, 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) {
|
|
LOG("Conflict (zero under current assignment)");
|
|
s.set_conflict({this, is_positive});
|
|
}
|
|
return;
|
|
}
|
|
if (q.is_never_zero()) {
|
|
if (is_positive) {
|
|
LOG("Conflict (never zero under current assignment)");
|
|
s.set_conflict({this, is_positive});
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (q.is_unilinear()) {
|
|
// a*x + b == 0
|
|
pvar v = q.var();
|
|
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);
|
|
|
|
|
|
rational val;
|
|
if (s.m_viable.find_viable(v, val) == dd::find_t::singleton)
|
|
s.propagate(v, val, {this, is_positive});
|
|
return;
|
|
}
|
|
|
|
// TODO: what other constraints can be extracted cheaply?
|
|
}
|
|
|
|
bool eq_constraint::is_always_false(bool is_positive) {
|
|
if (is_positive)
|
|
return p().is_never_zero();
|
|
else
|
|
return p().is_zero();
|
|
}
|
|
|
|
bool eq_constraint::is_currently_false(solver& s, bool is_positive) {
|
|
pdd r = p().subst_val(s.assignment());
|
|
if (is_positive)
|
|
return r.is_never_zero();
|
|
else
|
|
return r.is_zero();
|
|
}
|
|
|
|
bool eq_constraint::is_currently_true(solver& s, bool is_positive) {
|
|
pdd r = p().subst_val(s.assignment());
|
|
if (is_positive)
|
|
return r.is_zero();
|
|
else
|
|
return r.is_never_zero();
|
|
}
|
|
|
|
inequality eq_constraint::as_inequality(bool is_positive) const {
|
|
pdd zero = p() - p();
|
|
if (is_positive)
|
|
// p <= 0
|
|
return inequality(p(), zero, false, this);
|
|
else
|
|
// 0 < p
|
|
return inequality(zero, p(), true, this);
|
|
}
|
|
|
|
unsigned eq_constraint::hash() const {
|
|
return p().hash();
|
|
}
|
|
|
|
bool eq_constraint::operator==(constraint const& other) const {
|
|
return other.is_eq() && p() == other.to_eq().p();
|
|
}
|
|
|
|
}
|