3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-11-22 21:51:27 +00:00

use indexed root expressions id add_zero_assumption

Signed-off-by: Lev Nachmanson <levnach@hotmail.com>
This commit is contained in:
Lev Nachmanson 2025-11-18 16:35:27 -10:00
parent 43465accc6
commit 64ea6fa2c3
2 changed files with 44 additions and 25 deletions

View file

@ -281,30 +281,49 @@ namespace nlsat {
}; };
void add_zero_assumption(polynomial_ref& p) { void add_zero_assumption(polynomial_ref& p) {
// If p is of the form p1^n1 * ... * pk^nk, // Build a square-free representative of p so that we can speak about
// then only the factors that are zero in the current interpretation needed to be considered. // a specific root that coincides with the current assignment.
// I don't want to create a nested conjunction in the clause. polynomial_ref q(m_pm);
// Then, I assert p_i1 * ... * p_im != 0 m_pm.square_free(p, q);
{ if (is_zero(q) || is_const(q)) {
restore_factors _restore(m_factors, m_factors_save); SASSERT(!sign(q));
factor(p, m_factors); TRACE(nlsat_explain, tout << "cannot form zero assumption from constant polynomial " << q << "\n";);
unsigned num_factors = m_factors.size(); return;
m_zero_fs.reset();
m_is_even.reset();
polynomial_ref f(m_pm);
for (unsigned i = 0; i < num_factors; i++) {
f = m_factors.get(i);
if (is_zero(sign(f))) {
m_zero_fs.push_back(m_factors.get(i));
m_is_even.push_back(false);
} }
var y = max_var(q);
SASSERT(y != null_var);
if (y == null_var)
return;
SASSERT(m_assignment.is_assigned(y));
// Substitute all assigned variables except y to obtain qsub
// and make sure its discriminant does not vanish at the model.
polynomial_ref disc(m_pm);
disc = discriminant(q, y);
int const disc_sign = sign(disc);
SASSERT(disc_sign != 0);
if (disc_sign == 0)
NOT_IMPLEMENTED_YET();
scoped_anum_vector & roots = m_roots_tmp;
roots.reset();
// Isolate the roots of qsub by providing the assignment with y unassigned.
m_am.isolate_roots(q, undef_var_assignment(m_assignment, y), roots);
anum const & y_val = m_assignment.value(y);
unsigned root_idx = 0;
for (unsigned i = 0; i < roots.size(); ++i)
if (m_am.compare(y_val, roots[i]) == 0) {
root_idx = i + 1; // roots are 1-based
break;
} }
}
SASSERT(!m_zero_fs.empty()); // one of the factors must be zero in the current interpretation, since p is zero in it. VERIFY(root_idx > 0);
literal l = m_solver.mk_ineq_literal(atom::EQ, m_zero_fs.size(), m_zero_fs.data(), m_is_even.data());
l.neg(); TRACE(nlsat_explain,
TRACE(nlsat_explain, tout << "adding (zero assumption) literal:\n"; display(tout, l); tout << "\n";); tout << "adding zero-assumption root literal for ";
add_literal(l); display_var(tout, y); tout << " using root[" << root_idx << "] of " << q << "\n";);
add_root_literal(atom::ROOT_EQ, y, root_idx, q);
} }
void add_simple_assumption(atom::kind k, poly * p, bool sign = false) { void add_simple_assumption(atom::kind k, poly * p, bool sign = false) {

View file

@ -1139,7 +1139,7 @@ namespace nlsat {
used_vars[v] = true; used_vars[v] = true;
} }
display(out << "(echo \"#" << m_lemma_count++ << ":" << annotation << ":", n, cls) << "\")\n"; display(out << "(echo \"#" << m_lemma_count++ << ":" << annotation << ":", n, cls) << "\")\n";
out << "(set-logic ALL)\n"; out << "(set-logic NRA)\n";
out << "(set-option :rlimit " << m_lemma_rlimit << ")\n"; out << "(set-option :rlimit " << m_lemma_rlimit << ")\n";
if (is_valid) { if (is_valid) {
display_smt2_bool_decls(out, used_bools); display_smt2_bool_decls(out, used_bools);
@ -2260,7 +2260,7 @@ namespace nlsat {
} }
} }
out << "(echo \"#" << m_lemma_count++ << ":assignment lemma " << comment.str() << "\")\n"; out << "(echo \"#" << m_lemma_count++ << ":assignment lemma " << comment.str() << "\")\n";
out << "(set-logic ALL)\n"; out << "(set-logic NRA)\n";
out << "(set-option :rlimit " << m_lemma_rlimit << ")\n"; out << "(set-option :rlimit " << m_lemma_rlimit << ")\n";
display_smt2_bool_decls(out, used_bools); display_smt2_bool_decls(out, used_bools);
display_smt2_arith_decls(out, used_vars); display_smt2_arith_decls(out, used_vars);