mirror of
https://github.com/Z3Prover/z3
synced 2025-09-12 20:51:27 +00:00
t
Signed-off-by: Lev Nachmanson <levnach@hotmail.com>
This commit is contained in:
parent
bce5ad38a9
commit
a4f9eee822
1 changed files with 36 additions and 24 deletions
|
@ -51,6 +51,7 @@ namespace nlsat {
|
||||||
anum_manager& m_am;
|
anum_manager& m_am;
|
||||||
std::vector<property> m_Q; // the set of properties to prove
|
std::vector<property> m_Q; // the set of properties to prove
|
||||||
bool m_fail = false;
|
bool m_fail = false;
|
||||||
|
bool m_Q_changed = false; // tracks mutations to m_Q for fixed-point iteration
|
||||||
// Property precedence relation stored as pairs (lesser, greater)
|
// Property precedence relation stored as pairs (lesser, greater)
|
||||||
std::vector<std::pair<prop_enum, prop_enum>> m_p_relation;
|
std::vector<std::pair<prop_enum, prop_enum>> m_p_relation;
|
||||||
// Transitive closure matrix: dom[a][b] == true iff a ▹ b (a strictly dominates b).
|
// Transitive closure matrix: dom[a][b] == true iff a ▹ b (a strictly dominates b).
|
||||||
|
@ -472,10 +473,18 @@ namespace nlsat {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Part A of construct_interval: apply pre-conditions (line 8-11 scaffolding)
|
// Part A of construct_interval: apply pre-conditions (line 8-11 scaffolding)
|
||||||
bool apply_property_rules(unsigned i, prop_enum prop_to_avoid) {
|
bool apply_property_rules(unsigned i, prop_enum prop_to_avoid, result_struct* rs) {
|
||||||
std::vector<property> to_refine = greatest_to_refine(i, prop_to_avoid);
|
// Iterate until no mutation to m_Q occurs (fixed-point). We avoid copying m_Q
|
||||||
for (const auto& p: to_refine)
|
// by using a change flag that is set by mutating helpers (add_to_Q_if_new / erase_from_Q).
|
||||||
apply_pre(p);
|
if (m_fail) return false;
|
||||||
|
do {
|
||||||
|
m_Q_changed = false;
|
||||||
|
std::vector<property> to_refine = greatest_to_refine(i, prop_to_avoid);
|
||||||
|
for (const auto& p : to_refine) {
|
||||||
|
apply_pre(p, rs);
|
||||||
|
if (m_fail) return false;
|
||||||
|
}
|
||||||
|
} while (m_Q_changed && !m_fail);
|
||||||
return !m_fail;
|
return !m_fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -509,6 +518,7 @@ namespace nlsat {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_Q.push_back(pr);
|
m_Q.push_back(pr);
|
||||||
|
m_Q_changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void remove_level_i_from_Q(std::vector<property> & Q, unsigned i) {
|
void remove_level_i_from_Q(std::vector<property> & Q, unsigned i) {
|
||||||
|
@ -517,15 +527,24 @@ namespace nlsat {
|
||||||
Q.end());
|
Q.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void erase_from_Q(const property& p) {
|
||||||
|
auto it = std::find_if(m_Q.begin(), m_Q.end(), [&](const property & q) {
|
||||||
|
return q.prop_tag == p.prop_tag && q.poly == p.poly && q.level == p.level && q.s_idx == p.s_idx;
|
||||||
|
});
|
||||||
|
SASSERT(it != m_Q.end());
|
||||||
|
m_Q.erase(it);
|
||||||
|
m_Q_changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
result_struct construct_interval(unsigned i) {
|
result_struct construct_interval(unsigned i) {
|
||||||
result_struct ret;
|
result_struct ret;
|
||||||
if (!apply_property_rules(i, prop_enum::sgn_inv_irreducible)) {
|
if (!apply_property_rules(i, prop_enum::sgn_inv_irreducible, nullptr)) {
|
||||||
ret.fail = true;
|
ret.fail = true;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
build_representation(i, ret);
|
build_representation(i, ret);
|
||||||
apply_property_rules(i, prop_enum(prop_enum::holds));
|
apply_property_rules(i, prop_enum(prop_enum::holds), & ret);
|
||||||
|
|
||||||
// (moved Rule 1.1 precondition handling into apply_pre_connected)
|
// (moved Rule 1.1 precondition handling into apply_pre_connected)
|
||||||
|
|
||||||
|
@ -534,7 +553,6 @@ namespace nlsat {
|
||||||
remove_level_i_from_Q(ret.Q, i);
|
remove_level_i_from_Q(ret.Q, i);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extracted helper: handle ord_inv(discriminant_{x_{i+1}}(p)) for an_del pre-processing
|
// Extracted helper: handle ord_inv(discriminant_{x_{i+1}}(p)) for an_del pre-processing
|
||||||
void add_ord_inv_discriminant_for(const property& p) {
|
void add_ord_inv_discriminant_for(const property& p) {
|
||||||
polynomial_ref disc(m_pm);
|
polynomial_ref disc(m_pm);
|
||||||
|
@ -571,14 +589,6 @@ namespace nlsat {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void erase_from_Q(const property& p) {
|
|
||||||
auto it = std::find_if(m_Q.begin(), m_Q.end(), [&](const property & q) {
|
|
||||||
return q.prop_tag == p.prop_tag && q.poly == p.poly && q.level == p.level && q.s_idx == p.s_idx;
|
|
||||||
});
|
|
||||||
SASSERT(it != m_Q.end());
|
|
||||||
m_Q.erase(it);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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) {
|
||||||
|
@ -618,7 +628,7 @@ 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) {
|
void apply_pre_connected(const property & p, result_struct* rs) {
|
||||||
TRACE(levelwise, tout << "connected:";
|
TRACE(levelwise, tout << "connected:";
|
||||||
if (p.level != static_cast<unsigned>(-1)) tout << " level=" << p.level;
|
if (p.level != static_cast<unsigned>(-1)) tout << " level=" << p.level;
|
||||||
tout << std::endl;);
|
tout << std::endl;);
|
||||||
|
@ -631,25 +641,27 @@ namespace nlsat {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// p.level > 0
|
||||||
|
if (!rs) return; // no change since the interval etc is not there
|
||||||
// Rule 1.1 precondition: when processing connected(i) we must ensure the next lower level
|
// Rule 1.1 precondition: when processing connected(i) we must ensure the next lower level
|
||||||
// has connected(i-1) and repr(I,s) available. Add those markers to m_Q so they propagate.
|
// has connected(i-1) and repr(I,s) available. Add those markers to m_Q so they propagate.
|
||||||
if (p.level > 0) {
|
|
||||||
polynomial_ref empty(m_pm);
|
polynomial_ref empty(m_pm);
|
||||||
add_to_Q_if_new(property(prop_enum::connected, empty, /*level*/ p.level - 1));
|
add_to_Q_if_new(property(prop_enum::connected, empty, /*level*/ p.level - 1));
|
||||||
add_to_Q_if_new(property(prop_enum::repr, empty, /*level*/ p.level - 1));
|
add_to_Q_if_new(property(prop_enum::repr, empty, /*level*/ p.level - 1));
|
||||||
}
|
|
||||||
|
|
||||||
// todo!!!! add missing preconditions
|
// todo!!!! add missing preconditions
|
||||||
// connected property has been processed
|
// connected property has been processed
|
||||||
erase_from_Q(p);
|
erase_from_Q(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
void apply_pre(const property& p) {
|
void apply_pre(const property& p, result_struct* rs) {
|
||||||
TRACE(levelwise, display(tout << "property p:", p) << std::endl;);
|
TRACE(levelwise, display(tout << "property p:", p) << std::endl;);
|
||||||
if (p.prop_tag == prop_enum::an_del)
|
if (p.prop_tag == prop_enum::an_del)
|
||||||
apply_pre_an_del(p);
|
apply_pre_an_del(p);
|
||||||
else if (p.prop_tag == prop_enum::connected)
|
else if (p.prop_tag == prop_enum::connected)
|
||||||
apply_pre_connected(p);
|
apply_pre_connected(p, rs );
|
||||||
else
|
else
|
||||||
NOT_IMPLEMENTED_YET();
|
NOT_IMPLEMENTED_YET();
|
||||||
}
|
}
|
||||||
|
@ -665,7 +677,7 @@ namespace nlsat {
|
||||||
);
|
);
|
||||||
std::vector<symbolic_interval> ret;
|
std::vector<symbolic_interval> ret;
|
||||||
m_Q = seed_properties(); // Q is the set of properties on level m_n
|
m_Q = seed_properties(); // Q is the set of properties on level m_n
|
||||||
apply_property_rules(m_n, prop_enum::_count); // reduce the level by one to be consumed by construct_interval
|
apply_property_rules(m_n, prop_enum::_count, nullptr); // reduce the level by one to be consumed by construct_interval
|
||||||
for (unsigned i = m_n; --i > 0; ) {
|
for (unsigned i = m_n; --i > 0; ) {
|
||||||
auto result = construct_interval(i);
|
auto result = construct_interval(i);
|
||||||
if (result.fail)
|
if (result.fail)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue