mirror of
https://github.com/Z3Prover/z3
synced 2026-02-28 19:01:29 +00:00
Merge pull request #8770 from Z3Prover/lws
Optimizes the substitution of a non-nullified witness by an lc or a disc if they are added to the projection and do not vanish.
This commit is contained in:
commit
66d19c4d3f
4 changed files with 31 additions and 15 deletions
|
|
@ -55,6 +55,8 @@ namespace nlsat {
|
|||
|
||||
unsigned m_level = 0; // current level being processed
|
||||
unsigned m_spanning_tree_threshold = 3; // minimum both-side count for spanning tree
|
||||
bool m_witness_subs_lc = true;
|
||||
bool m_witness_subs_disc = false;
|
||||
unsigned m_l_rf = UINT_MAX; // position of lower bound in m_rel.m_rfunc
|
||||
unsigned m_u_rf = UINT_MAX; // position of upper bound in m_rel.m_rfunc, UINT_MAX in section case
|
||||
|
||||
|
|
@ -260,6 +262,8 @@ namespace nlsat {
|
|||
m_I.emplace_back(m_pm);
|
||||
|
||||
m_spanning_tree_threshold = m_solver.lws_spt_threshold();
|
||||
m_witness_subs_lc = m_solver.lws_witness_subs_lc();
|
||||
m_witness_subs_disc = m_solver.lws_witness_subs_disc();
|
||||
}
|
||||
|
||||
// Handle a polynomial whose every coefficient evaluates to zero at the sample.
|
||||
|
|
@ -443,7 +447,7 @@ namespace nlsat {
|
|||
lc = m_pm.coeff(p, x, deg);
|
||||
TRACE(lws, m_pm.display(tout << " adding lc: ", lc) << "\n";);
|
||||
request_factorized(lc);
|
||||
if (add_nzero_coeff && lc && sign(lc))
|
||||
if (add_nzero_coeff && m_witness_subs_disc && lc && sign(lc))
|
||||
add_nzero_coeff = false;
|
||||
}
|
||||
|
||||
|
|
@ -455,7 +459,7 @@ namespace nlsat {
|
|||
// If p is nullified at some point then at this point discriminant well be evaluated
|
||||
// to zero, as can be seen from the Sylvester matrix which would
|
||||
// have at least one zero row.
|
||||
if (add_nzero_coeff && sign(disc)) // we can avoid adding a nonzero_coeff if sign(disc) != 0
|
||||
if (add_nzero_coeff && m_witness_subs_disc && sign(disc)) // we can avoid adding a nonzero_coeff if sign(disc) != 0
|
||||
add_nzero_coeff = false;
|
||||
}
|
||||
}
|
||||
|
|
@ -1165,7 +1169,7 @@ namespace nlsat {
|
|||
// No need for an additional coefficient witness in this case.
|
||||
polynomial_ref witness = m_witnesses[i];
|
||||
if (add_lc && witness && !is_const(witness))
|
||||
if (lc && !is_zero(lc) && sign(lc))
|
||||
if (lc && !is_zero(lc) && m_witness_subs_lc && sign(lc))
|
||||
witness = polynomial_ref(m_pm);
|
||||
|
||||
add_projection_for_poly(p, m_level, witness, add_lc, add_disc);
|
||||
|
|
@ -1300,25 +1304,27 @@ namespace nlsat {
|
|||
collect_non_null_witnesses();
|
||||
add_adjacent_root_resultants();
|
||||
|
||||
// Projections (coeff witness, disc, leading coeff).
|
||||
// Projection: witness, disc, lc
|
||||
for (unsigned i = 0; i < m_level_ps.size(); ++i) {
|
||||
polynomial_ref p(m_level_ps.get(i), m_pm);
|
||||
polynomial_ref lc(m_pm);
|
||||
unsigned deg = m_pm.degree(p, m_n);
|
||||
lc = m_pm.coeff(p, m_n, deg);
|
||||
|
||||
// Projective delineability optimization, Lemma 3.2 of "Projective Delineability
|
||||
// for Single Cell Construction": if p is projectively delineable on R,
|
||||
// ldcf(p)(s) != 0, and p has no real roots at s, then p is delineable on R
|
||||
// without requiring sign-invariance of the leading coefficient.
|
||||
// Projective delineability is ensured by adding the discriminant, Theorem 3.1,
|
||||
// and non-nullification is ensured by the witness.
|
||||
bool add_lc = true;
|
||||
if (!poly_has_roots(i))
|
||||
if (lc && !is_zero(lc) && sign(lc))
|
||||
add_lc = false;
|
||||
if (!poly_has_roots(i) && lc && !is_zero(lc) && sign(lc)) {
|
||||
add_lc = false;
|
||||
polynomial_ref null_ref(m_pm);
|
||||
m_witnesses[i] = null_ref;
|
||||
}
|
||||
|
||||
// if the leading coefficient is already non-zero at the sample
|
||||
// AND we're adding lc, we do not need to project an additional non-null coefficient witness.
|
||||
polynomial_ref witness = m_witnesses[i];
|
||||
if (add_lc && witness && !is_const(witness))
|
||||
if (lc && !is_zero(lc) && sign(lc))
|
||||
witness = polynomial_ref(m_pm); // zero the witnsee as lc will be the witness
|
||||
add_projection_for_poly(p, m_n, witness, add_lc, true); //true to add the discriminant
|
||||
add_projection_for_poly(p, m_n, m_witnesses[i], add_lc, true); //true to add the discriminant
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,5 +24,7 @@ def_module_params('nlsat',
|
|||
('known_sat_assignment_file_name', STRING, "", "the file name of a known solution: used for debugging only"),
|
||||
('lws', BOOL, True, "apply levelwise."),
|
||||
('lws_spt_threshold', UINT, 4, "minimum both-side polynomial count to apply spanning tree optimization; < 2 disables spanning tree"),
|
||||
('lws_witness_subs_lc', BOOL, True, "try substitute the non-nullified witness by the lc"),
|
||||
('lws_witness_subs_disc', BOOL, True, "try substitute the non-nullified witness by the discriminant"),
|
||||
('canonicalize', BOOL, True, "canonicalize polynomials.")
|
||||
))
|
||||
|
|
|
|||
|
|
@ -250,7 +250,9 @@ namespace nlsat {
|
|||
std::string m_debug_known_solution_file_name;
|
||||
bool m_apply_lws;
|
||||
bool m_last_conflict_used_lws = false; // Track if last conflict explanation used levelwise
|
||||
unsigned m_lws_spt_threshold = 3;
|
||||
unsigned m_lws_spt_threshold = 3;
|
||||
bool m_lws_witness_subs_lc = true;
|
||||
bool m_lws_witness_subs_disc = false;
|
||||
imp(solver& s, ctx& c):
|
||||
m_ctx(c),
|
||||
m_solver(s),
|
||||
|
|
@ -312,6 +314,8 @@ namespace nlsat {
|
|||
m_debug_known_solution_file_name = p.known_sat_assignment_file_name();
|
||||
m_apply_lws = p.lws();
|
||||
m_lws_spt_threshold = p.lws_spt_threshold(); // 0 disables spanning tree
|
||||
m_lws_witness_subs_lc = p. lws_witness_subs_lc();
|
||||
m_lws_witness_subs_disc = p.lws_witness_subs_disc();
|
||||
m_check_lemmas |= !(m_debug_known_solution_file_name.empty());
|
||||
|
||||
m_ism.set_seed(m_random_seed);
|
||||
|
|
@ -4718,4 +4722,6 @@ namespace nlsat {
|
|||
}
|
||||
bool solver::apply_levelwise() const { return m_imp->m_apply_lws; }
|
||||
unsigned solver::lws_spt_threshold() const { return m_imp->m_lws_spt_threshold; }
|
||||
bool solver::lws_witness_subs_lc() const { return m_imp->m_lws_witness_subs_lc; }
|
||||
bool solver::lws_witness_subs_disc() const { return m_imp->m_lws_witness_subs_disc; }
|
||||
};
|
||||
|
|
|
|||
|
|
@ -249,6 +249,8 @@ namespace nlsat {
|
|||
assignment& sample();
|
||||
bool apply_levelwise() const;
|
||||
unsigned lws_spt_threshold() const;
|
||||
bool lws_witness_subs_lc() const;
|
||||
bool lws_witness_subs_disc() const;
|
||||
void reset();
|
||||
void collect_statistics(statistics & st);
|
||||
void reset_statistics();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue