mirror of
https://github.com/Z3Prover/z3
synced 2025-10-08 17:01:55 +00:00
t
Signed-off-by: Lev Nachmanson <levnach@hotmail.com>
This commit is contained in:
parent
0274982adb
commit
204560288e
4 changed files with 98 additions and 66 deletions
|
@ -19,7 +19,7 @@ namespace nlsat {
|
||||||
// Local enums reused from previous scaffolding
|
// Local enums reused from previous scaffolding
|
||||||
enum class property_mapping_case : unsigned { case1 = 0, case2 = 1, case3 = 2 };
|
enum class property_mapping_case : unsigned { case1 = 0, case2 = 1, case3 = 2 };
|
||||||
|
|
||||||
enum class prop_enum : unsigned {
|
enum prop_enum {
|
||||||
ir_ord,
|
ir_ord,
|
||||||
an_del,
|
an_del,
|
||||||
non_null,
|
non_null,
|
||||||
|
@ -27,13 +27,13 @@ namespace nlsat {
|
||||||
sgn_inv,
|
sgn_inv,
|
||||||
connected,
|
connected,
|
||||||
an_sub,
|
an_sub,
|
||||||
sample,
|
sample_holds,
|
||||||
repr,
|
repr,
|
||||||
holds,
|
holds,
|
||||||
_count
|
_count
|
||||||
};
|
};
|
||||||
|
|
||||||
unsigned prop_count() { return static_cast<unsigned>(prop_enum::_count);}
|
unsigned prop_count() { return static_cast<unsigned>(_count);}
|
||||||
|
|
||||||
struct levelwise::impl {
|
struct levelwise::impl {
|
||||||
// Utility: call fn for each distinct irreducible factor of poly
|
// Utility: call fn for each distinct irreducible factor of poly
|
||||||
|
@ -97,10 +97,17 @@ namespace nlsat {
|
||||||
// max_x plays the role of n in algorith 1 of the levelwise paper.
|
// 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)
|
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) {
|
||||||
TRACE(levelwise, tout << "m_n:" << m_n << "\n";);
|
TRACE(lws, tout << "m_n:" << m_n << "\n";);
|
||||||
m_I.resize(m_n);
|
// m_I holds one symbolic_interval per level. symbolic_interval is not default
|
||||||
|
// constructible (it requires a polynomial::manager), so using resize() would
|
||||||
|
// attempt to default-construct elements and fail to compile. Instead we
|
||||||
|
// explicitly emplace objects initialized with the polynomial manager.
|
||||||
|
m_I.reserve(m_n);
|
||||||
|
for (unsigned i = 0; i < m_n; ++i)
|
||||||
|
m_I.emplace_back(m_pm);
|
||||||
m_Q.resize(m_n+1);
|
m_Q.resize(m_n+1);
|
||||||
}
|
}
|
||||||
|
// end constructor
|
||||||
|
|
||||||
|
|
||||||
// helper overload so callers can pass either raw poly* or polynomial_ref
|
// helper overload so callers can pass either raw poly* or polynomial_ref
|
||||||
|
@ -188,7 +195,7 @@ namespace nlsat {
|
||||||
if (root_vals.size() < 2) return true;
|
if (root_vals.size() < 2) return true;
|
||||||
std::sort(root_vals.begin(), root_vals.end(), [&](auto const & a, auto const & b){ return m_am.lt(a.first, b.first); });
|
std::sort(root_vals.begin(), root_vals.end(), [&](auto const & a, auto const & b){ return m_am.lt(a.first, b.first); });
|
||||||
std::set<std::pair<unsigned,unsigned>> added_pairs;
|
std::set<std::pair<unsigned,unsigned>> added_pairs;
|
||||||
TRACE(levelwise,
|
TRACE(lws,
|
||||||
tout << "root_vals:";
|
tout << "root_vals:";
|
||||||
for (const auto& rv : root_vals) {
|
for (const auto& rv : root_vals) {
|
||||||
tout << " [";
|
tout << " [";
|
||||||
|
@ -214,7 +221,7 @@ namespace nlsat {
|
||||||
polynomial_ref r(m_pm);
|
polynomial_ref r(m_pm);
|
||||||
r = resultant(polynomial_ref(p1, m_pm), polynomial_ref(p2, m_pm), m_n);
|
r = resultant(polynomial_ref(p1, m_pm), polynomial_ref(p2, m_pm), m_n);
|
||||||
if (is_const(r)) continue;
|
if (is_const(r)) continue;
|
||||||
TRACE(levelwise, tout << "resultant: "; ::nlsat::display(tout, m_solver, r); tout << std::endl;);
|
TRACE(lws, tout << "resultant: "; ::nlsat::display(tout, m_solver, r); tout << std::endl;);
|
||||||
if (is_zero(r)) {
|
if (is_zero(r)) {
|
||||||
NOT_IMPLEMENTED_YET();// ambiguous resultant - not handled yet
|
NOT_IMPLEMENTED_YET();// ambiguous resultant - not handled yet
|
||||||
return false;
|
return false;
|
||||||
|
@ -301,7 +308,7 @@ namespace nlsat {
|
||||||
}
|
}
|
||||||
|
|
||||||
//works on m_level
|
//works on m_level
|
||||||
bool apply_property_rules(prop_enum prop_to_avoid, bool has_repr) {
|
bool apply_property_rules(prop_enum prop_to_avoid, bool have_representation) {
|
||||||
SASSERT (!m_fail);
|
SASSERT (!m_fail);
|
||||||
std::vector<property> avoided;
|
std::vector<property> avoided;
|
||||||
auto& q = m_Q[m_level];
|
auto& q = m_Q[m_level];
|
||||||
|
@ -311,7 +318,7 @@ namespace nlsat {
|
||||||
avoided.push_back(p);
|
avoided.push_back(p);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
apply_pre(p, has_repr);
|
apply_pre(p, have_representation);
|
||||||
if (m_fail) break;
|
if (m_fail) break;
|
||||||
}
|
}
|
||||||
for (auto & p : avoided)
|
for (auto & p : avoided)
|
||||||
|
@ -335,7 +342,7 @@ namespace nlsat {
|
||||||
return m_am.lt(a.val, b.val);
|
return m_am.lt(a.val, b.val);
|
||||||
});
|
});
|
||||||
compute_interval_from_sorted_roots(E, m_I[m_level]);
|
compute_interval_from_sorted_roots(E, m_I[m_level]);
|
||||||
TRACE(levelwise, display(tout << "m_I[" << m_level << "]:", m_I[m_level]) << std::endl;);
|
TRACE(lws, display(tout << "m_I[" << m_level << "]:", m_I[m_level]) << std::endl;);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 1a: collect E the set of root functions
|
// Step 1a: collect E the set of root functions
|
||||||
|
@ -350,7 +357,7 @@ namespace nlsat {
|
||||||
m_am.isolate_roots(polynomial_ref(p, m_pm), undef_var_assignment(sample(), m_level), roots);
|
m_am.isolate_roots(polynomial_ref(p, m_pm), undef_var_assignment(sample(), m_level), roots);
|
||||||
|
|
||||||
unsigned num_roots = roots.size();
|
unsigned num_roots = roots.size();
|
||||||
TRACE(levelwise,
|
TRACE(lws,
|
||||||
tout << "roots (" << num_roots << "):";
|
tout << "roots (" << num_roots << "):";
|
||||||
for (unsigned kk = 0; kk < num_roots; ++kk) {
|
for (unsigned kk = 0; kk < num_roots; ++kk) {
|
||||||
tout << " "; m_am.display(tout, roots[kk]);
|
tout << " "; m_am.display(tout, roots[kk]);
|
||||||
|
@ -369,7 +376,7 @@ namespace nlsat {
|
||||||
if (q.prop_tag != pr.prop_tag) continue;
|
if (q.prop_tag != pr.prop_tag) continue;
|
||||||
if (q.poly != pr.poly) continue;
|
if (q.poly != pr.poly) continue;
|
||||||
if (q.s_idx != pr.s_idx) continue;
|
if (q.s_idx != pr.s_idx) continue;
|
||||||
TRACE(levelwise, display(tout << "matched q:", q) << std::endl;);
|
TRACE(lws, display(tout << "matched q:", q) << std::endl;);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_Q[level].push(pr);
|
m_Q[level].push(pr);
|
||||||
|
@ -383,7 +390,7 @@ namespace nlsat {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACE(levelwise, display(tout << "m_Q:") << std::endl;);
|
TRACE(lws, display(tout << "m_Q:") << std::endl;);
|
||||||
|
|
||||||
build_representation();
|
build_representation();
|
||||||
SASSERT(invariant());
|
SASSERT(invariant());
|
||||||
|
@ -393,7 +400,7 @@ namespace nlsat {
|
||||||
void add_ord_inv_discriminant_for(const property& p) {
|
void add_ord_inv_discriminant_for(const property& p) {
|
||||||
polynomial::polynomial_ref disc(m_pm);
|
polynomial::polynomial_ref disc(m_pm);
|
||||||
disc = discriminant(p.poly, max_var(p.poly));
|
disc = discriminant(p.poly, max_var(p.poly));
|
||||||
TRACE(levelwise, tout << "p:"; display(tout, p) << "\n";
|
TRACE(lws, tout << "p:"; display(tout, p) << "\n";
|
||||||
::nlsat::display(tout << "discriminant: ", m_solver, disc) << "\n";);
|
::nlsat::display(tout << "discriminant: ", m_solver, disc) << "\n";);
|
||||||
if (!is_const(disc)) {
|
if (!is_const(disc)) {
|
||||||
for_each_distinct_factor(disc, [&](polynomial::polynomial_ref f) {
|
for_each_distinct_factor(disc, [&](polynomial::polynomial_ref f) {
|
||||||
|
@ -433,13 +440,13 @@ namespace nlsat {
|
||||||
// Extracted helper: check preconditions for an_del property; returns true if ok, false otherwise.
|
// Extracted helper: check preconditions for an_del property; returns true if ok, false otherwise.
|
||||||
bool precondition_on_an_del(const property& p) {
|
bool precondition_on_an_del(const property& p) {
|
||||||
if (!p.poly) {
|
if (!p.poly) {
|
||||||
TRACE(levelwise, tout << "apply_pre: an_del with null poly -> fail" << std::endl;);
|
TRACE(lws, tout << "apply_pre: an_del with null poly -> fail" << std::endl;);
|
||||||
m_fail = true;
|
m_fail = true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// If p is nullified on the sample for its level we must abort (Rule 4.1)
|
// If p is nullified on the sample for its level we must abort (Rule 4.1)
|
||||||
if (coeffs_are_zeroes_on_sample(p.poly, m_pm, sample(), m_am)) {
|
if (coeffs_are_zeroes_on_sample(p.poly, m_pm, sample(), m_am)) {
|
||||||
TRACE(levelwise, tout << "Rule 4.1: polynomial nullified at sample -> failing" << std::endl;);
|
TRACE(lws, tout << "Rule 4.1: polynomial nullified at sample -> failing" << std::endl;);
|
||||||
m_fail = true;
|
m_fail = true;
|
||||||
NOT_IMPLEMENTED_YET();
|
NOT_IMPLEMENTED_YET();
|
||||||
return false;
|
return false;
|
||||||
|
@ -463,11 +470,11 @@ namespace nlsat {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pre-processing for connected(i) (Rule 4.11)
|
// Pre-processing for connected(i) (Rule 4.11)
|
||||||
void apply_pre_connected(const property & p, bool has_repr) {
|
void apply_pre_connected(const property & p, bool have_representation) {
|
||||||
// Rule 4.11 special-case: if the connected property refers to level 0 there's nothing to refine
|
// Rule 4.11 special-case: if the connected property refers to level 0 there's nothing to refine
|
||||||
// further; just remove the property from Q and return.
|
// further; just remove the property from Q and return.
|
||||||
if (m_level == 0) {
|
if (m_level == 0) {
|
||||||
TRACE(levelwise, tout << "apply_pre_connected: level 0 -> erasing connected property and returning" << std::endl;);
|
TRACE(lws, tout << "apply_pre_connected: level 0 -> erasing connected property and returning" << std::endl;);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -477,7 +484,7 @@ namespace nlsat {
|
||||||
|
|
||||||
mk_prop(prop_enum::connected, m_level - 1);
|
mk_prop(prop_enum::connected, m_level - 1);
|
||||||
mk_prop(prop_enum::repr, m_level - 1);
|
mk_prop(prop_enum::repr, m_level - 1);
|
||||||
if (!has_repr) {
|
if (!have_representation) {
|
||||||
return; // no change since the cell representation is not available
|
return; // no change since the cell representation is not available
|
||||||
}
|
}
|
||||||
NOT_IMPLEMENTED_YET();
|
NOT_IMPLEMENTED_YET();
|
||||||
|
@ -486,7 +493,7 @@ namespace nlsat {
|
||||||
}
|
}
|
||||||
|
|
||||||
void apply_pre_non_null(const property& p) {
|
void apply_pre_non_null(const property& p) {
|
||||||
TRACE(levelwise, tout << "p:"; display(tout, p) << std::endl;);
|
TRACE(lws, tout << "p:"; display(tout, p) << std::endl;);
|
||||||
// First try subrule 1 of Rule 4.2. If it succeeds we do not apply the fallback (subrule 2).
|
// First try subrule 1 of Rule 4.2. If it succeeds we do not apply the fallback (subrule 2).
|
||||||
if (try_non_null_via_coeffs(p))
|
if (try_non_null_via_coeffs(p))
|
||||||
return;
|
return;
|
||||||
|
@ -511,7 +518,7 @@ namespace nlsat {
|
||||||
bool try_non_null_via_coeffs(const property& p) {
|
bool try_non_null_via_coeffs(const property& p) {
|
||||||
unsigned level = max_var(p.poly);
|
unsigned level = max_var(p.poly);
|
||||||
if (have_non_zero_const(p.poly, level)) {
|
if (have_non_zero_const(p.poly, level)) {
|
||||||
TRACE(levelwise, tout << "have a non-zero const coefficient\n";);
|
TRACE(lws, tout << "have a non-zero const coefficient\n";);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -543,7 +550,7 @@ namespace nlsat {
|
||||||
void apply_pre_non_null_fallback(const property& p) {
|
void apply_pre_non_null_fallback(const property& p) {
|
||||||
// basic sanity checks
|
// basic sanity checks
|
||||||
if (!p.poly) {
|
if (!p.poly) {
|
||||||
TRACE(levelwise, tout << "apply_pre_non_null_fallback: null poly -> fail" << std::endl;);
|
TRACE(lws, tout << "apply_pre_non_null_fallback: null poly -> fail" << std::endl;);
|
||||||
m_fail = true;
|
m_fail = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -558,12 +565,12 @@ namespace nlsat {
|
||||||
// compute discriminant w.r.t. the variable at p.level
|
// compute discriminant w.r.t. the variable at p.level
|
||||||
polynomial_ref disc(m_pm);
|
polynomial_ref disc(m_pm);
|
||||||
disc = discriminant(p.poly, level);
|
disc = discriminant(p.poly, level);
|
||||||
TRACE(levelwise, ::nlsat::display(tout << "discriminant: ", m_solver, disc) << "\n";);
|
TRACE(lws, ::nlsat::display(tout << "discriminant: ", m_solver, disc) << "\n";);
|
||||||
|
|
||||||
// If discriminant evaluates to zero at the sample, we cannot proceed
|
// If discriminant evaluates to zero at the sample, we cannot proceed
|
||||||
// (ambiguous multiplicity) -> fail per instruction
|
// (ambiguous multiplicity) -> fail per instruction
|
||||||
if (sign(disc, sample(), m_am) == 0) {
|
if (sign(disc, sample(), m_am) == 0) {
|
||||||
TRACE(levelwise, tout << "apply_pre_non_null_fallback: discriminant vanishes at sample -> failing" << std::endl;);
|
TRACE(lws, tout << "apply_pre_non_null_fallback: discriminant vanishes at sample -> failing" << std::endl;);
|
||||||
m_fail = true;
|
m_fail = true;
|
||||||
NOT_IMPLEMENTED_YET();
|
NOT_IMPLEMENTED_YET();
|
||||||
return;
|
return;
|
||||||
|
@ -590,6 +597,7 @@ namespace nlsat {
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Rule 4.13
|
||||||
The property repr(I, s) holds on R if and only if I.l ∈ irExpr(I.l.p, s) (if I.l ̸= −∞), I.u ∈ irExpr(I.u.p, s)
|
The property repr(I, s) holds on R if and only if I.l ∈ irExpr(I.l.p, s) (if I.l ̸= −∞), I.u ∈ irExpr(I.u.p, s)
|
||||||
(if I.u ̸= ∞) respectively I.b ∈ irExpr(I.b.p, s) and one of the following holds:
|
(if I.u ̸= ∞) respectively I.b ∈ irExpr(I.b.p, s) and one of the following holds:
|
||||||
• I = (sector, l, u), dom(θl,s ) ∩ dom(θu,s ) ⊇ R ↓[i−1] and R = {(r, r′) | r ∈ R ↓[i−1], r′ ∈ (θl,s (r), θu,s (r))};
|
• I = (sector, l, u), dom(θl,s ) ∩ dom(θu,s ) ⊇ R ↓[i−1] and R = {(r, r′) | r ∈ R ↓[i−1], r′ ∈ (θl,s (r), θu,s (r))};
|
||||||
|
@ -602,9 +610,9 @@ or
|
||||||
*/
|
*/
|
||||||
void apply_pre_repr(const property& p) {
|
void apply_pre_repr(const property& p) {
|
||||||
const auto& I = m_I[m_level];
|
const auto& I = m_I[m_level];
|
||||||
TRACE(levelwise, display(tout << "interval m_I[" << m_level << "]\n", I) << "\n";);
|
TRACE(lws, display(tout << "interval m_I[" << m_level << "]\n", I) << "\n";);
|
||||||
mk_prop(prop_enum::holds, m_level -1);
|
mk_prop(prop_enum::holds, m_level -1);
|
||||||
mk_prop(prop_enum::sample, m_level -1);
|
mk_prop(sample_holds, m_level -1);
|
||||||
if (I.is_section()) {
|
if (I.is_section()) {
|
||||||
NOT_IMPLEMENTED_YET();
|
NOT_IMPLEMENTED_YET();
|
||||||
} else {
|
} else {
|
||||||
|
@ -615,10 +623,10 @@ or
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void apply_pre_sample(const property& p, bool has_repr) {
|
void apply_pre_sample(const property& p, bool have_representation) {
|
||||||
if (m_level == 0)
|
if (m_level == 0)
|
||||||
return;
|
return;
|
||||||
mk_prop(prop_enum::sample, m_level - 1);
|
mk_prop(sample_holds, m_level - 1);
|
||||||
mk_prop(prop_enum::repr, m_level - 1);
|
mk_prop(prop_enum::repr, m_level - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -635,14 +643,14 @@ or
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Rule 4.6. Let i ∈ N, R ⊆ Ri, s ∈ R_{i−1}, and realRoots(p(s, xi )) = ∅. */
|
/* Rule 4.6. Let i ∈ N, R ⊆ Ri, s ∈ R_{i−1}, and realRoots(p(s, xi )) = ∅. */
|
||||||
void apply_pre_sgn_inv(const property& p, bool has_repr) {
|
void apply_pre_sgn_inv(const property& p, bool have_representation) {
|
||||||
SASSERT(is_irreducible(p.poly));
|
SASSERT(is_irreducible(p.poly));
|
||||||
scoped_anum_vector roots(m_am);
|
scoped_anum_vector roots(m_am);
|
||||||
SASSERT(max_var(p.poly) == m_level);
|
SASSERT(max_var(p.poly) == m_level);
|
||||||
m_am.isolate_roots(p.poly, undef_var_assignment(sample(), m_level), roots);
|
m_am.isolate_roots(p.poly, undef_var_assignment(sample(), m_level), roots);
|
||||||
if (roots.size() == 0) {
|
if (roots.size() == 0) {
|
||||||
//Rule 4.6 sample(s)(R), an_del(p)(R) ⊢ sgn_inv(p)(R)
|
//Rule 4.6 sample(s)(R), an_del(p)(R) ⊢ sgn_inv(p)(R)
|
||||||
mk_prop(prop_enum::sample, m_level - 1);
|
mk_prop(sample_holds, m_level - 1);
|
||||||
mk_prop(prop_enum::an_del, p.poly, m_level);
|
mk_prop(prop_enum::an_del, p.poly, m_level);
|
||||||
}
|
}
|
||||||
/* Rule 4.8. Let i ∈ N>0 , R ⊆ Ri
|
/* Rule 4.8. Let i ∈ N>0 , R ⊆ Ri
|
||||||
|
@ -675,15 +683,15 @@ or
|
||||||
p(s) ̸= 0, sample(s)(R), sgn_inv(p)(R) ⊢ ord_inv(p)(R)
|
p(s) ̸= 0, sample(s)(R), sgn_inv(p)(R) ⊢ ord_inv(p)(R)
|
||||||
p(s)= 0, sample(s)(R), an_sub(i− 1)(R), connected(i)(R), sgn_inv(p)(R), an_del(p)(R) ⊢ ord_inv(p)(R)
|
p(s)= 0, sample(s)(R), an_sub(i− 1)(R), connected(i)(R), sgn_inv(p)(R), an_del(p)(R) ⊢ ord_inv(p)(R)
|
||||||
*/
|
*/
|
||||||
void apply_pre_ord_inv(const property& p, bool has_repr) {
|
void apply_pre_ord_inv(const property& p, bool have_representation) {
|
||||||
SASSERT(p.prop_tag == prop_enum::ord_inv && is_irreducible(p.poly));
|
SASSERT(p.prop_tag == prop_enum::ord_inv && is_irreducible(p.poly));
|
||||||
unsigned level = max_var(p.poly);
|
unsigned level = max_var(p.poly);
|
||||||
auto sign_on_sample = sign(p.poly, sample(), m_am);
|
auto sign_on_sample = sign(p.poly, sample(), m_am);
|
||||||
if (sign_on_sample) {
|
if (sign_on_sample) {
|
||||||
mk_prop(prop_enum::sample, level);
|
mk_prop(sample_holds, level);
|
||||||
mk_prop(prop_enum::sgn_inv, p.poly, level);
|
mk_prop(prop_enum::sgn_inv, p.poly, level);
|
||||||
} else { // sign is zero
|
} else { // sign is zero
|
||||||
mk_prop(prop_enum::sample, level);
|
mk_prop(sample_holds, level);
|
||||||
mk_prop(prop_enum::an_sub, level - 1);
|
mk_prop(prop_enum::an_sub, level - 1);
|
||||||
mk_prop(prop_enum::connected, level);
|
mk_prop(prop_enum::connected, level);
|
||||||
mk_prop(prop_enum::sgn_inv, p.poly, p.s_idx, level);
|
mk_prop(prop_enum::sgn_inv, p.poly, p.s_idx, level);
|
||||||
|
@ -691,15 +699,15 @@ or
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void apply_pre(const property& p, bool has_repr) {
|
void apply_pre(const property& p, bool have_representation) {
|
||||||
TRACE(levelwise, tout << "apply_pre BEGIN m_Q:"; display(tout) << std::endl;
|
TRACE(lws, tout << "apply_pre BEGIN m_Q:"; display(tout) << std::endl;
|
||||||
display(tout << "pre p:", p) << std::endl;);
|
display(tout << "pre p:", p) << std::endl;);
|
||||||
switch (p.prop_tag) {
|
switch (p.prop_tag) {
|
||||||
case prop_enum::an_del:
|
case prop_enum::an_del:
|
||||||
apply_pre_an_del(p);
|
apply_pre_an_del(p);
|
||||||
break;
|
break;
|
||||||
case prop_enum::connected:
|
case prop_enum::connected:
|
||||||
apply_pre_connected(p, has_repr);
|
apply_pre_connected(p, have_representation);
|
||||||
break;
|
break;
|
||||||
case prop_enum::non_null:
|
case prop_enum::non_null:
|
||||||
apply_pre_non_null(p);
|
apply_pre_non_null(p);
|
||||||
|
@ -712,21 +720,21 @@ or
|
||||||
break;
|
break;
|
||||||
case prop_enum::holds:
|
case prop_enum::holds:
|
||||||
break; // ignore the bottom of refinement
|
break; // ignore the bottom of refinement
|
||||||
case prop_enum::sample:
|
case sample_holds:
|
||||||
apply_pre_sample(p, has_repr);
|
apply_pre_sample(p, have_representation);
|
||||||
break;
|
break;
|
||||||
case prop_enum::sgn_inv:
|
case prop_enum::sgn_inv:
|
||||||
apply_pre_sgn_inv(p, has_repr);
|
apply_pre_sgn_inv(p, have_representation);
|
||||||
break;
|
break;
|
||||||
case prop_enum::ord_inv:
|
case prop_enum::ord_inv:
|
||||||
apply_pre_ord_inv(p, has_repr);
|
apply_pre_ord_inv(p, have_representation);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
TRACE(levelwise, display(tout << "not impl: p", p));
|
TRACE(lws, display(tout << "not impl: p", p));
|
||||||
NOT_IMPLEMENTED_YET();
|
NOT_IMPLEMENTED_YET();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
TRACE(levelwise, tout << "apply_pre END m_Q:"; display(tout) << std::endl;);
|
TRACE(lws, tout << "apply_pre END m_Q:"; display(tout) << std::endl;);
|
||||||
SASSERT(invariant());
|
SASSERT(invariant());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -743,7 +751,7 @@ or
|
||||||
|
|
||||||
// return an empty vector on failure, otherwise returns the cell representations with intervals
|
// return an empty vector on failure, otherwise returns the cell representations with intervals
|
||||||
std::vector<symbolic_interval> single_cell() {
|
std::vector<symbolic_interval> single_cell() {
|
||||||
TRACE(levelwise,
|
TRACE(lws,
|
||||||
m_solver.display_assignment(tout << "sample()") << std::endl;
|
m_solver.display_assignment(tout << "sample()") << std::endl;
|
||||||
tout << "m_P:\n";
|
tout << "m_P:\n";
|
||||||
for (const auto & p: m_P) {
|
for (const auto & p: m_P) {
|
||||||
|
@ -772,7 +780,7 @@ or
|
||||||
case prop_enum::sgn_inv: return "sgn_inv";
|
case prop_enum::sgn_inv: return "sgn_inv";
|
||||||
case prop_enum::connected: return "connected";
|
case prop_enum::connected: return "connected";
|
||||||
case prop_enum::an_sub: return "an_sub";
|
case prop_enum::an_sub: return "an_sub";
|
||||||
case prop_enum::sample: return "sample";
|
case sample_holds: return "sample";
|
||||||
case prop_enum::repr: return "repr";
|
case prop_enum::repr: return "repr";
|
||||||
case prop_enum::holds: return "holds";
|
case prop_enum::holds: return "holds";
|
||||||
case prop_enum::_count: return "_count";
|
case prop_enum::_count: return "_count";
|
||||||
|
@ -811,25 +819,8 @@ or
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ostream& display(std::ostream& out, const symbolic_interval& I) const {
|
std::ostream& display(std::ostream& out, const symbolic_interval& I) const {
|
||||||
if (I.section) {
|
return ::nlsat::display(out, m_solver, I);
|
||||||
out << "Section:\n";
|
}
|
||||||
if (I.l == nullptr)
|
|
||||||
out << "not defined\n";
|
|
||||||
else
|
|
||||||
::nlsat::display(out, m_solver, I.l);
|
|
||||||
} else {
|
|
||||||
out << "Sector: (";
|
|
||||||
if (I.l_inf())
|
|
||||||
out << "-oo,";
|
|
||||||
else
|
|
||||||
::nlsat::display(out, m_solver, I.l) << ",";
|
|
||||||
if (I.u_inf())
|
|
||||||
out << "+oo)";
|
|
||||||
else
|
|
||||||
::nlsat::display(out, m_solver, I.u) << ")";
|
|
||||||
}
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -844,3 +835,34 @@ or
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace nlsat
|
} // namespace nlsat
|
||||||
|
|
||||||
|
// Free pretty-printer for symbolic_interval
|
||||||
|
std::ostream& nlsat::display(std::ostream& out, solver& s, levelwise::symbolic_interval const& I) {
|
||||||
|
if (I.section) {
|
||||||
|
out << "Section: ";
|
||||||
|
if (I.l == nullptr)
|
||||||
|
out << "(undef)";
|
||||||
|
else {
|
||||||
|
::nlsat::display(out, s, I.l);
|
||||||
|
out << "[root_index=" << I.l_index << "]";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
out << "Sector: (";
|
||||||
|
if (I.l_inf())
|
||||||
|
out << "-oo";
|
||||||
|
else {
|
||||||
|
::nlsat::display(out, s, I.l);
|
||||||
|
out << "[i=" << I.l_index << "]";
|
||||||
|
}
|
||||||
|
out << ", ";
|
||||||
|
if (I.u_inf())
|
||||||
|
out << "+oo";
|
||||||
|
else {
|
||||||
|
::nlsat::display(out, s, I.u);
|
||||||
|
out << "[i=" << I.u_index << "]";
|
||||||
|
}
|
||||||
|
out << ")";
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
|
@ -13,19 +13,24 @@ namespace nlsat {
|
||||||
};
|
};
|
||||||
struct symbolic_interval {
|
struct symbolic_interval {
|
||||||
bool section = false;
|
bool section = false;
|
||||||
poly* l = nullptr;
|
polynomial_ref l;
|
||||||
unsigned l_index; // the root index
|
unsigned l_index; // the root index
|
||||||
poly* u = nullptr;
|
polynomial_ref u;
|
||||||
unsigned u_index; // the root index
|
unsigned u_index; // the root index
|
||||||
bool l_inf() const { return l == nullptr; }
|
bool l_inf() const { return l == nullptr; }
|
||||||
bool u_inf() const { return u == nullptr; }
|
bool u_inf() const { return u == nullptr; }
|
||||||
bool is_section() const { return section; }
|
bool is_section() const { return section; }
|
||||||
bool is_sector() const { return !section; }
|
bool is_sector() const { return !section; }
|
||||||
poly* section_poly() {
|
polynomial_ref& section_poly() {
|
||||||
SASSERT(is_section());
|
SASSERT(is_section());
|
||||||
return l;
|
return l;
|
||||||
}
|
}
|
||||||
|
symbolic_interval(polynomial::manager & pm):l(pm), u(pm) {}
|
||||||
};
|
};
|
||||||
|
// Free pretty-printer declared here so external modules (e.g., nlsat_explain) can
|
||||||
|
// display intervals without depending on levelwise internals.
|
||||||
|
// Implemented in levelwise.cpp
|
||||||
|
friend std::ostream& display(std::ostream& out, solver& s, symbolic_interval const& I);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -43,5 +48,7 @@ namespace nlsat {
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
|
// Free pretty-printer (non-member) for levelwise::symbolic_interval
|
||||||
|
std::ostream& display(std::ostream& out, solver& s, levelwise::symbolic_interval const& I);
|
||||||
|
|
||||||
} // namespace nlsat
|
} // namespace nlsat
|
||||||
|
|
|
@ -1209,6 +1209,8 @@ namespace nlsat {
|
||||||
polynomial_ref_vector samples(m_pm);
|
polynomial_ref_vector samples(m_pm);
|
||||||
levelwise lws(m_solver, ps, max_x, sample(), m_pm, m_am);
|
levelwise lws(m_solver, ps, max_x, sample(), m_pm, m_am);
|
||||||
auto cell = lws.single_cell();
|
auto cell = lws.single_cell();
|
||||||
|
TRACE(lws, for (unsigned i = 0; i < cell.size(); i++)
|
||||||
|
display(tout << "I[" << i << "]:", m_solver, cell[i]) << "\n";);
|
||||||
if (x < max_x)
|
if (x < max_x)
|
||||||
cac_add_cell_lits(ps, x, samples);
|
cac_add_cell_lits(ps, x, samples);
|
||||||
|
|
||||||
|
|
|
@ -551,6 +551,7 @@ X(Global, linear_equation_mk, "linear equation mk")
|
||||||
X(Global, list, "list")
|
X(Global, list, "list")
|
||||||
X(Global, literal_occ, "literal occ")
|
X(Global, literal_occ, "literal occ")
|
||||||
X(Global, lp_core, "lp core")
|
X(Global, lp_core, "lp core")
|
||||||
|
X(Global, lws, "levelwise")
|
||||||
X(Global, macro_bug, "macro bug")
|
X(Global, macro_bug, "macro bug")
|
||||||
X(Global, macro_finder, "macro finder")
|
X(Global, macro_finder, "macro finder")
|
||||||
X(Global, macro_insert, "macro insert")
|
X(Global, macro_insert, "macro insert")
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue