mirror of
https://github.com/Z3Prover/z3
synced 2025-09-03 16:48:06 +00:00
preprocess the input of levelwise to drop a level
Signed-off-by: Lev Nachmanson <levnach@hotmail.com>
This commit is contained in:
parent
c87e7c312a
commit
98d8083d15
2 changed files with 84 additions and 6 deletions
|
@ -44,6 +44,7 @@ namespace nlsat {
|
|||
var m_n;
|
||||
pmanager& m_pm;
|
||||
anum_manager& m_am;
|
||||
polynomial_ref_vector m_generated; // storage for resultants we create
|
||||
std::vector<property> m_Q; // the set of properties to prove
|
||||
bool m_fail = false;
|
||||
// Property precedence relation stored as pairs (lesser, greater)
|
||||
|
@ -57,7 +58,7 @@ namespace nlsat {
|
|||
|
||||
// max_x plays the role of n in algorith 1 of the levelwise paper.
|
||||
impl(solver& solver, polynomial_ref_vector const& ps, var max_x, assignment const& s, pmanager& pm, anum_manager& am)
|
||||
: m_solver(solver), m_P(ps), m_n(max_x), m_pm(pm), m_am(am) {
|
||||
: m_solver(solver), m_P(ps), m_n(max_x), m_pm(pm), m_am(am), m_generated(m_pm) {
|
||||
TRACE(levelwise, tout << "m_n:" << m_n << "\n";);
|
||||
init_property_relation();
|
||||
}
|
||||
|
@ -123,12 +124,89 @@ namespace nlsat {
|
|||
|
||||
std::vector<property> seed_properties() {
|
||||
std::vector<property> Q;
|
||||
|
||||
/*
|
||||
Recall the description of MCSAT in Section 1.2. We are interested in when MCSAT resolves theory
|
||||
conflicts. I.e. when there is a set of constraints C in real variables x0, . . . , x_{n-1} , x_{n-1}+1 that should be
|
||||
satisfied according to the Boolean model and an assignment s : {x0, . . . , x_{n-1} } → R such that s cannot be
|
||||
extended to a value for x_{n-1}+1 satisfying C . The task then is to exclude a cell around s that generalizes
|
||||
this conflict, i.e. a region cell where the reason for unsatisfiability of C is invariant.
|
||||
This reason of unsatisfiability is maintained when all input polynomials are sign-invariant on the
|
||||
generalized cell. To achieve this, we could do a full McCallum projection step, obtaining a set of
|
||||
properties of one level below allowing to construct a cell around s.
|
||||
However, this is already too strong, as we need the set of input polynomials P = {p | (p ∼ 0) ∈
|
||||
C } : Q[x0, . . . , x_{n-1} , x_n] to be delineable over a cell containing the current sample s ∈ Rn for main-
|
||||
taining the desired property. We achieve this by determining the indexed root expression of the real
|
||||
roots of the set {p ∈ factors(P )| level(p) = n } over s in x_n and ordering them such that ξ1(s) ≤
|
||||
ξ2(s) ≤. . . ≤ ξk (s). Finally, we ensure that all lower level factors {p ∈ factors(P )| level(p) < n} are
|
||||
sign-invariant, check that each polynomial is not nullified (if not, we stop), make each polynomial
|
||||
individually delineable and add the resultants of the pair of polynomials (ξ j.p, ξ j+1.p) for j ∈ [1..k − 1].
|
||||
Thus, the input of the presented one-cell algorithm is given as
|
||||
Q = {sgn_inv(p) | p ∈ factors(P ), level(p) < n }
|
||||
∪ {an_del(p) | p ∈ factors(P ), level(p)= n }
|
||||
∪ {ord_inv(resxn+1 (ξ j.p, ξ j+1.p)) | j ∈ [k− 1]}.
|
||||
*/
|
||||
// Algorithm 1: initial goals are sgn_inv(p, s) for p in ps at current level of max_x
|
||||
for (unsigned i = 0; i < m_P.size(); ++i) {
|
||||
poly* p = m_P.get(i);
|
||||
Q.push_back(property{ prop_enum::sgn_inv_irreducible, p, /*s_idx*/0, /* level */ m_n - 1});
|
||||
unsigned level = m_pm.max_var(p);
|
||||
if (level < m_n)
|
||||
Q.push_back(property{ prop_enum::sgn_inv_irreducible, p, /*s_idx*/0, /* level */ level});
|
||||
else if (level == m_n)
|
||||
Q.push_back(property{ prop_enum::an_del, p, /* s_idx*/ 0, level });
|
||||
else {
|
||||
SASSERT(level <= m_n);
|
||||
}
|
||||
}
|
||||
|
||||
// compute indexed roots for polynomials at level m_n, order them and add ord_inv(resultant) properties ---
|
||||
// collect polynomials whose main variable is m_n
|
||||
std::vector<poly*> ps_of_n_level;
|
||||
for (unsigned i = 0; i < m_P.size(); ++i) {
|
||||
poly* p = m_P.get(i);
|
||||
if (m_pm.max_var(p) == m_n)
|
||||
ps_of_n_level.push_back(p);
|
||||
}
|
||||
|
||||
if (ps_of_n_level.size() >= 2) {
|
||||
// collect all roots (as algebraic numbers) together with their originating indexed_root_expr
|
||||
std::vector<std::pair<scoped_anum, indexed_root_expr>> root_vals;
|
||||
for (auto * p : ps_of_n_level) {
|
||||
scoped_anum_vector roots(m_am);
|
||||
m_am.isolate_roots(polynomial_ref(p, m_pm), undef_var_assignment(sample(), m_n), roots);
|
||||
unsigned num_roots = roots.size();
|
||||
for (unsigned k = 0; k < num_roots; ++k) {
|
||||
scoped_anum v(m_am);
|
||||
m_am.set(v, roots[k]);
|
||||
root_vals.emplace_back(std::move(v), indexed_root_expr{p, k + 1});
|
||||
}
|
||||
}
|
||||
|
||||
// order roots by their algebraic value (ascending)
|
||||
if (root_vals.size() >= 2) {
|
||||
std::sort(root_vals.begin(), root_vals.end(), [&](auto const & a, auto const & b){
|
||||
return m_am.lt(a.first, b.first);
|
||||
});
|
||||
|
||||
// add resultants of adjacent roots
|
||||
for (size_t j = 0; j + 1 < root_vals.size(); ++j) {
|
||||
poly* p1 = root_vals[j].second.p;
|
||||
poly* p2 = root_vals[j+1].second.p;
|
||||
polynomial_ref r(m_pm);
|
||||
r =resultant(polynomial_ref(p1, m_pm), polynomial_ref(p2, m_pm), m_n);
|
||||
if (is_const(r)) continue;
|
||||
if (is_zero(r) ) {
|
||||
NOT_IMPLEMENTED_YET(); // not sure how to process
|
||||
}
|
||||
// keep the resultant alive in m_generated
|
||||
m_generated.push_back(r.get());
|
||||
poly* rp = m_generated.get(m_generated.size() - 1);
|
||||
unsigned lvl = m_pm.max_var(rp);
|
||||
Q.push_back(property{ prop_enum::ord_inv_irreducible, rp, /*s_idx*/ 0u, lvl });
|
||||
}
|
||||
}
|
||||
}
|
||||
// ---------------------------------------------------------------------------------
|
||||
|
||||
return Q;
|
||||
}
|
||||
|
||||
|
@ -447,7 +525,7 @@ namespace nlsat {
|
|||
tout << "m_P:\n";
|
||||
for (const auto & p: m_P) {
|
||||
::nlsat::display(tout, m_solver, polynomial_ref(p, m_pm)) << std::endl;
|
||||
tout << "max0_var:" << m_pm.max_var(p) << std::endl;
|
||||
tout << "max_var:" << m_pm.max_var(p) << std::endl;
|
||||
}
|
||||
);
|
||||
std::vector<symbolic_interval> ret;
|
||||
|
|
|
@ -1220,8 +1220,8 @@ namespace nlsat {
|
|||
// Remark: after vanishing coefficients are eliminated, ps may not contain max_x anymore
|
||||
|
||||
polynomial_ref_vector samples(m_pm);
|
||||
// levelwise lws(m_solver, ps, max_x, sample(), m_pm, m_am);
|
||||
//auto cell = lws.single_cell();
|
||||
levelwise lws(m_solver, ps, max_x, sample(), m_pm, m_am);
|
||||
auto cell = lws.single_cell();
|
||||
if (x < max_x)
|
||||
cac_add_cell_lits(ps, x, samples);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue