mirror of
https://github.com/Z3Prover/z3
synced 2025-06-27 08:28:44 +00:00
cleanup
This commit is contained in:
parent
57cb999061
commit
b25451bd87
3 changed files with 31 additions and 35 deletions
|
@ -151,25 +151,25 @@ namespace polysat {
|
||||||
// create equality literal for unassigned variable.
|
// create equality literal for unassigned variable.
|
||||||
// return new_eq if there is a new literal.
|
// return new_eq if there is a new literal.
|
||||||
|
|
||||||
sat::check_result core::check() {
|
lbool core::assign_variable() {
|
||||||
if (m_var_queue.empty())
|
if (m_var_queue.empty())
|
||||||
return final_check();
|
return l_true;
|
||||||
m_var = m_var_queue.min_var();
|
m_var = m_var_queue.min_var();
|
||||||
CTRACE("bv", is_assigned(m_var), display(tout << "v" << m_var << " is assigned\n"););
|
CTRACE("bv", is_assigned(m_var), display(tout << "v" << m_var << " is assigned\n"););
|
||||||
SASSERT(!is_assigned(m_var));
|
SASSERT(!is_assigned(m_var));
|
||||||
|
|
||||||
auto& var_value = m_values[m_var];
|
auto& var_value = m_values[m_var];
|
||||||
switch (m_viable.find_viable(m_var, var_value)) {
|
switch (m_viable.find_viable(m_var, var_value)) {
|
||||||
case find_t::empty:
|
case find_t::empty:
|
||||||
viable_conflict(m_var);
|
viable_conflict(m_var);
|
||||||
return sat::check_result::CR_CONTINUE;
|
return l_false;
|
||||||
case find_t::singleton: {
|
case find_t::singleton: {
|
||||||
auto p = var2pdd(m_var).mk_var(m_var);
|
auto p = var2pdd(m_var).mk_var(m_var);
|
||||||
auto sc = m_constraints.eq(p, var_value);
|
auto sc = m_constraints.eq(p, var_value);
|
||||||
TRACE("bv", tout << "check-propagate v" << m_var << " := " << var_value << " " << sc << "\n");
|
TRACE("bv", tout << "check-propagate v" << m_var << " := " << var_value << " " << sc << "\n");
|
||||||
auto d = s.propagate(sc, m_viable.explain(), "viable-propagate");
|
auto d = s.propagate(sc, m_viable.explain(), "viable-propagate");
|
||||||
propagate_assignment(m_var, var_value, d);
|
propagate_assignment(m_var, var_value, d);
|
||||||
return sat::check_result::CR_CONTINUE;
|
return l_false;
|
||||||
}
|
}
|
||||||
case find_t::multiple: {
|
case find_t::multiple: {
|
||||||
dependency d = null_dependency;
|
dependency d = null_dependency;
|
||||||
|
@ -188,19 +188,31 @@ namespace polysat {
|
||||||
// let core assign equality.
|
// let core assign equality.
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return sat::check_result::CR_CONTINUE;
|
return l_false;
|
||||||
}
|
}
|
||||||
case find_t::resource_out:
|
case find_t::resource_out:
|
||||||
TRACE("bv", tout << "check-resource out v" << m_var << "\n");
|
TRACE("bv", tout << "check-resource out v" << m_var << "\n");
|
||||||
return sat::check_result::CR_GIVEUP;
|
return l_undef;
|
||||||
}
|
}
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
return sat::check_result::CR_GIVEUP;
|
return l_undef;
|
||||||
}
|
}
|
||||||
|
|
||||||
sat::check_result core::final_check() {
|
sat::check_result core::check() {
|
||||||
|
|
||||||
lbool r = l_true;
|
lbool r = l_true;
|
||||||
|
|
||||||
|
switch (assign_variable()) {
|
||||||
|
case l_true:
|
||||||
|
break;
|
||||||
|
case l_false:
|
||||||
|
return sat::check_result::CR_CONTINUE;
|
||||||
|
case l_undef:
|
||||||
|
return sat::check_result::CR_GIVEUP;
|
||||||
|
// or:
|
||||||
|
// r = l_undef;
|
||||||
|
// break;
|
||||||
|
}
|
||||||
|
|
||||||
switch (m_monomials.refine()) {
|
switch (m_monomials.refine()) {
|
||||||
case l_true:
|
case l_true:
|
||||||
break;
|
break;
|
||||||
|
@ -268,7 +280,6 @@ namespace polysat {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// First propagate Boolean assignment, then propagate value assignment
|
|
||||||
bool core::propagate() {
|
bool core::propagate() {
|
||||||
if (m_qhead == m_prop_queue.size())
|
if (m_qhead == m_prop_queue.size())
|
||||||
return false;
|
return false;
|
||||||
|
@ -293,7 +304,6 @@ namespace polysat {
|
||||||
TRACE("bv", tout << "propagate " << sc << " using " << dep << " := " << value << "\n");
|
TRACE("bv", tout << "propagate " << sc << " using " << dep << " := " << value << "\n");
|
||||||
if (sc.is_always_false()) {
|
if (sc.is_always_false()) {
|
||||||
s.set_conflict({dep}, "infeasible assignment");
|
s.set_conflict({dep}, "infeasible assignment");
|
||||||
decay_activity();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
rational var_value;
|
rational var_value;
|
||||||
|
|
|
@ -90,9 +90,8 @@ namespace polysat {
|
||||||
|
|
||||||
void add_watch(unsigned idx, unsigned var);
|
void add_watch(unsigned idx, unsigned var);
|
||||||
|
|
||||||
sat::check_result final_check();
|
lbool assign_variable();
|
||||||
|
|
||||||
|
|
||||||
void add_axiom(signed_constraint sc);
|
void add_axiom(signed_constraint sc);
|
||||||
|
|
||||||
unsigned m_activity_inc = 128;
|
unsigned m_activity_inc = 128;
|
||||||
|
|
|
@ -10,18 +10,6 @@ Author:
|
||||||
Nikolaj Bjorner (nbjorner) 2021-03-19
|
Nikolaj Bjorner (nbjorner) 2021-03-19
|
||||||
Jakob Rath 2021-04-6
|
Jakob Rath 2021-04-6
|
||||||
|
|
||||||
|
|
||||||
TODO: preserve falsification
|
|
||||||
- each rule selects a certain premises that are problematic.
|
|
||||||
If the problematic premise is false under the current assignment, the newly inferred
|
|
||||||
literal should also be false in the assignment in order to preserve conflicts.
|
|
||||||
|
|
||||||
|
|
||||||
TODO: when we check that 'x' is "unary":
|
|
||||||
- in principle, 'x' could be any polynomial. However, we need to divide the lhs by x, and we don't have general polynomial division yet.
|
|
||||||
so for now we just allow the form 'value*variable'.
|
|
||||||
(extension to arbitrary monomials for 'x' should be fairly easy too)
|
|
||||||
|
|
||||||
--*/
|
--*/
|
||||||
#include "sat/smt/polysat/core.h"
|
#include "sat/smt/polysat/core.h"
|
||||||
#include "sat/smt/polysat/saturation.h"
|
#include "sat/smt/polysat/saturation.h"
|
||||||
|
@ -125,16 +113,15 @@ namespace polysat {
|
||||||
pdd x = c.var(v);
|
pdd x = c.var(v);
|
||||||
pdd y = x;
|
pdd y = x;
|
||||||
pdd z = x;
|
pdd z = x;
|
||||||
auto& C = c.cs();
|
|
||||||
|
|
||||||
if (!i.is_xY_l_xZ(v, y, z))
|
if (!i.is_xY_l_xZ(v, y, z))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto ovfl = C.umul_ovfl(x, y);
|
auto ovfl = C.umul_ovfl(x, y);
|
||||||
if (i.is_strict())
|
if (i.is_strict())
|
||||||
add_clause("[x] yx < zx ==> Ω*(x,y) \\/ y < z", { i.dep(), ovfl, C.ult(y, z)}, false);
|
add_clause("[x] yx < zx ==> Ω*(x,y) \\/ y < z", { i.dep(), ovfl, C.ult(y, z)}, true);
|
||||||
else
|
else
|
||||||
add_clause("[x] yx <= zx ==> Ω*(x,y) \\/ y <= z \\/ x = 0", { i.dep(), ovfl, C.eq(x), C.ule(y, z) }, false);
|
add_clause("[x] yx <= zx ==> Ω*(x,y) \\/ y <= z \\/ x = 0", { i.dep(), ovfl, C.eq(x), C.ule(y, z) }, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -149,14 +136,14 @@ namespace polysat {
|
||||||
auto y = c.var(v);
|
auto y = c.var(v);
|
||||||
pdd x = y;
|
pdd x = y;
|
||||||
pdd z = y;
|
pdd z = y;
|
||||||
auto& C = c.cs();
|
|
||||||
if (!i.is_Xy_l_XZ(v, x, z))
|
if (!i.is_Xy_l_XZ(v, x, z))
|
||||||
return;
|
return;
|
||||||
for (constraint_id id : constraint_iterator(c, [&](auto const& sc) { return inequality::is_l_v(y, sc); })) {
|
for (constraint_id id : constraint_iterator(c, [&](auto const& sc) { return inequality::is_l_v(y, sc); })) {
|
||||||
auto j = inequality::from_ule(c, id);
|
auto j = inequality::from_ule(c, id);
|
||||||
pdd const& z_prime = i.lhs();
|
pdd const& z_prime = i.lhs();
|
||||||
bool is_strict = i.is_strict() || j.is_strict();
|
bool is_strict = i.is_strict() || j.is_strict();
|
||||||
add_clause("[y] z' <= y & yx <= zx", { i.dep(), j.dep(), C.umul_ovfl(x, y), ineq(is_strict, z_prime * x, z * x) }, true);
|
add_clause("[y] z' <= y & yx <= zx ==> Ω*(x,y) \/ z'x <= zx",
|
||||||
|
{ i.dep(), j.dep(), C.umul_ovfl(x, y), ineq(is_strict, z_prime * x, z * x) }, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,14 +165,14 @@ namespace polysat {
|
||||||
auto j = inequality::from_ule(c, id);
|
auto j = inequality::from_ule(c, id);
|
||||||
auto y_prime = j.rhs();
|
auto y_prime = j.rhs();
|
||||||
bool is_strict = i.is_strict() || j.is_strict();
|
bool is_strict = i.is_strict() || j.is_strict();
|
||||||
add_clause("[z] z <= y' && yx <= zx", { i.dep(), j.dep(), c.umul_ovfl(x, y_prime), ineq(is_strict, y * x, y_prime * x) }, true);
|
add_clause("[z] z <= y' && yx <= zx ==> Ω*(x,y') \/ yx <= y'x",
|
||||||
|
{ i.dep(), j.dep(), c.umul_ovfl(x, y_prime), ineq(is_strict, y * x, y_prime * x) }, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ovfl(x, y) & ~Ovfl(y, z) ==> x > z
|
// Ovfl(x, y) & ~Ovfl(y, z) ==> x > z
|
||||||
void saturation::try_umul_ovfl(pvar v, umul_ovfl const& sc) {
|
void saturation::try_umul_ovfl(pvar v, umul_ovfl const& sc) {
|
||||||
auto p = sc.p(), q = sc.q();
|
auto p = sc.p(), q = sc.q();
|
||||||
auto& C = c.cs();
|
|
||||||
auto match_mul_arg = [&](auto const& sc2) {
|
auto match_mul_arg = [&](auto const& sc2) {
|
||||||
auto p2 = sc2.to_umul_ovfl().p(), q2 = sc2.to_umul_ovfl().q();
|
auto p2 = sc2.to_umul_ovfl().p(), q2 = sc2.to_umul_ovfl().q();
|
||||||
return p == p2 || p == q2 || q == p2 || q == q2;
|
return p == p2 || p == q2 || q == p2 || q == q2;
|
||||||
|
@ -209,9 +196,9 @@ namespace polysat {
|
||||||
auto d2 = c.get_dependency(id);
|
auto d2 = c.get_dependency(id);
|
||||||
auto [q1, q2] = extract_mul_args(sc2);
|
auto [q1, q2] = extract_mul_args(sc2);
|
||||||
if (sc.sign())
|
if (sc.sign())
|
||||||
add_clause("[y] ~ovfl(p, q1) & ovfl(p, q2) ==> q1 < q2", { d1, d2, C.ult(q1, q2) }, false);
|
add_clause("[y] ~ovfl(p, q1) & ovfl(p, q2) ==> q1 < q2", { d1, d2, C.ult(q1, q2) }, true);
|
||||||
else
|
else
|
||||||
add_clause("[y] ovfl(p, q1) & ~ovfl(p, q2) ==> q1 > q2", { d1, d2, C.ult(q2, q1)}, false);
|
add_clause("[y] ovfl(p, q1) & ~ovfl(p, q2) ==> q1 > q2", { d1, d2, C.ult(q2, q1)}, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue