mirror of
https://github.com/Z3Prover/z3
synced 2025-04-22 16:45:31 +00:00
introduce to_refine in rooted_table
Signed-off-by: Lev <levnach@hotmail.com>
This commit is contained in:
parent
403743cb30
commit
5599dc984c
2 changed files with 125 additions and 77 deletions
|
@ -143,9 +143,9 @@ struct solver::imp {
|
|||
|
||||
lp::impq vv(lpvar j) const { return m_lar_solver.get_column_value(j); }
|
||||
|
||||
lpvar var(const rooted_mon& rm) const {return m_monomials[rm.m_orig.m_i].var(); }
|
||||
lpvar var(const rooted_mon& rm) const {return m_monomials[rm.orig().m_i].var(); }
|
||||
|
||||
rational vvr(const rooted_mon& rm) const { return vvr(m_monomials[rm.m_orig.m_i].var()) * rm.m_orig.m_sign; }
|
||||
rational vvr(const rooted_mon& rm) const { return vvr(m_monomials[rm.orig().m_i].var()) * rm.orig().m_sign; }
|
||||
|
||||
rational vvr(const factor& f) const { return vvr(var(f)); }
|
||||
|
||||
|
@ -167,13 +167,13 @@ struct solver::imp {
|
|||
// by the flip_sign
|
||||
rational flip_sign(const factor& f) const {
|
||||
return f.is_var()?
|
||||
rational(1) : m_rm_table.vec()[f.index()].m_orig.sign();
|
||||
rational(1) : m_rm_table.vec()[f.index()].orig().sign();
|
||||
}
|
||||
|
||||
// the value of the rooted monomias is equal to the value of the variable multiplied
|
||||
// by the flip_sign
|
||||
rational flip_sign(const rooted_mon& m) const {
|
||||
return m.m_orig.sign();
|
||||
return m.orig().sign();
|
||||
}
|
||||
|
||||
// returns the monomial index
|
||||
|
@ -276,7 +276,7 @@ struct solver::imp {
|
|||
if (f.is_var()) {
|
||||
print_var(f.index(), out);
|
||||
} else {
|
||||
out << " rm = "; print_rooted_monomial_with_vars(m_rm_table.vec()[f.index()], out);
|
||||
out << " RM = "; print_rooted_monomial_with_vars(m_rm_table.vec()[f.index()], out);
|
||||
out << "\n orig mon = "; print_monomial_with_vars(m_monomials[m_rm_table.vec()[f.index()].orig_index()], out);
|
||||
}
|
||||
return out;
|
||||
|
@ -637,14 +637,15 @@ struct solver::imp {
|
|||
}
|
||||
|
||||
bool basic_sign_lemma_on_mon(unsigned i){
|
||||
TRACE("nla_solver", tout << "i = " << i << ", mon = "; print_monomial_with_vars(m_monomials[i], tout););
|
||||
const monomial& m = m_monomials[i];
|
||||
TRACE("nla_solver", tout << "i = " << i << ", mon = "; print_monomial_with_vars(m, tout););
|
||||
auto mons_to_explore = equiv_monomials(m,
|
||||
[this](lpvar j) {return eq_vars(j);},
|
||||
[this](const unsigned_vector& key) {return find_monomial(key);});
|
||||
|
||||
for (unsigned n : equiv_monomials(m, [this](lpvar j) {return eq_vars(j);},
|
||||
[this](const unsigned_vector& key) {return find_monomial(key);})
|
||||
) {
|
||||
for (unsigned n : mons_to_explore) {
|
||||
if (n == static_cast<unsigned>(-1) || n == i) continue;
|
||||
if (basic_sign_lemma_on_two_monomials(m_monomials[i], m_monomials[n]))
|
||||
if (basic_sign_lemma_on_two_monomials(m, m_monomials[n]))
|
||||
return true;
|
||||
}
|
||||
TRACE("nla_solver",);
|
||||
|
@ -654,7 +655,7 @@ struct solver::imp {
|
|||
const rooted_mon& mon_to_rooted_mon(const svector<lpvar>& vars) const {
|
||||
auto rit = m_rm_table.map().find(vars);
|
||||
SASSERT(rit != m_rm_table.map().end());
|
||||
unsigned rm_i = rit->second.m_i;
|
||||
unsigned rm_i = rit->second;
|
||||
return m_rm_table.vec()[rm_i];
|
||||
}
|
||||
|
||||
|
@ -757,7 +758,7 @@ struct solver::imp {
|
|||
return false;
|
||||
}
|
||||
|
||||
i = it->second.m_i;
|
||||
i = it->second;
|
||||
TRACE("nla_solver",);
|
||||
|
||||
SASSERT(lp::vectors_are_equal_(vars, m_rm_table.vec()[i].vars()));
|
||||
|
@ -895,7 +896,7 @@ struct solver::imp {
|
|||
// use the fact
|
||||
// 1 * 1 ... * 1 * x * 1 ... * 1 = x
|
||||
bool basic_lemma_for_mon_neutral_from_factors_to_monomial(const rooted_mon& rm, const factorization& f) {
|
||||
rational sign = rm.m_orig.m_sign;
|
||||
rational sign = rm.orig().m_sign;
|
||||
lpvar not_one = -1;
|
||||
|
||||
TRACE("nla_solver", tout << "f = "; print_factorization(f, tout););
|
||||
|
@ -1032,18 +1033,34 @@ struct solver::imp {
|
|||
return false;
|
||||
}
|
||||
|
||||
void init_rm_to_refine() {
|
||||
std::unordered_set<unsigned> ref;
|
||||
ref.insert(m_to_refine.begin(), m_to_refine.end());
|
||||
m_rm_table.init_to_refine(ref);
|
||||
}
|
||||
|
||||
unsigned random() {return m_lar_solver.settings().random_next();}
|
||||
|
||||
// use basic multiplication properties to create a lemma
|
||||
bool basic_lemma() {
|
||||
if (basic_sign_lemma())
|
||||
return true;
|
||||
|
||||
for (const rooted_mon& r : m_rm_table.vec()) {
|
||||
if (check_monomial(m_monomials[r.orig_index()]))
|
||||
continue;
|
||||
|
||||
init_rm_to_refine();
|
||||
const auto& rm_ref = m_rm_table.to_refine();
|
||||
unsigned start = random() % rm_ref.size();
|
||||
unsigned i = start;
|
||||
do {
|
||||
const rooted_mon& r = m_rm_table.vec()[rm_ref[i]];
|
||||
SASSERT (!check_monomial(m_monomials[r.orig_index()]));
|
||||
if (basic_lemma_for_mon(r)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (++i == m_rm_table.to_refine().size()) {
|
||||
i = 0;
|
||||
}
|
||||
} while(i != start);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1273,7 +1290,7 @@ struct solver::imp {
|
|||
TRACE("nla_solver_div", tout << "not in rooted";);
|
||||
return false;
|
||||
}
|
||||
b = factor(it->second.m_i, factor_type::RM);
|
||||
b = factor(it->second, factor_type::RM);
|
||||
TRACE("nla_solver_div", tout << "success div:"; print_factor(b, tout););
|
||||
return true;
|
||||
}
|
||||
|
@ -1421,34 +1438,37 @@ struct solver::imp {
|
|||
}
|
||||
|
||||
// collect all vars and rooted monomials with the same absolute
|
||||
// value as c and return them as factors
|
||||
// value as the absolute value af c and return them as factors
|
||||
vector<factor> factors_with_the_same_abs_val(const factor& c) const {
|
||||
vector<factor> r;
|
||||
std::unordered_set<lpvar> found_vars;
|
||||
std::unordered_set<unsigned> found_rm;
|
||||
TRACE("nla_solver", tout << "c = "; print_factor_with_vars(c, tout););
|
||||
for (lpvar i : m_vars_equivalence.get_vars_with_the_same_abs_val(vvr(c))) {
|
||||
SASSERT(abs(vvr(i)) == abs(vvr(c)));
|
||||
auto it = m_var_to_its_monomial.find(i);
|
||||
if (it == m_var_to_its_monomial.end()) {
|
||||
i = m_vars_equivalence.map_to_root(i);
|
||||
if (!contains(found_vars, i)) {
|
||||
found_vars.insert(i);
|
||||
r.push_back(factor(i, factor_type::VAR));
|
||||
TRACE("nla_solver", tout << "insering var = "; print_var(i, tout););
|
||||
}
|
||||
} else {
|
||||
const monomial& m = m_monomials[it->second];
|
||||
SASSERT(m.var() == i);
|
||||
SASSERT(abs(vvr(m)) == abs(vvr(c)));
|
||||
monomial_coeff mc = canonize_monomial(m);
|
||||
TRACE("nla_solver", tout << "m = "; print_monomial_with_vars(m, tout);
|
||||
tout << "mc = "; print_product_with_vars(mc.vars(), tout););
|
||||
|
||||
auto it = m_rm_table.map().find(mc.vars());
|
||||
SASSERT(it != m_rm_table.map().end());
|
||||
i = it->second.m_i;
|
||||
i = it->second;
|
||||
// SASSERT(abs(vvr(m_rm_table.vec()[i])) == abs(vvr(c)));
|
||||
if (!contains(found_rm, i)) {
|
||||
found_rm.insert(i);
|
||||
r.push_back(factor(i, factor_type::RM));
|
||||
TRACE("nla_solver", tout << "insering factor = "; print_factor_with_vars(factor(i, factor_type::RM), tout); );
|
||||
TRACE("nla_solver", tout << "inserting factor = "; print_factor_with_vars(factor(i, factor_type::RM), tout); );
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1461,7 +1481,7 @@ struct solver::imp {
|
|||
// ac[k] plays the role of c
|
||||
bool order_lemma_on_factor(const rooted_mon& rm, const factorization& ac, unsigned k) {
|
||||
auto c = ac[k];
|
||||
TRACE("nla_solver", tout << "k = " << k << ", c = "; print_factor(c, tout); );
|
||||
TRACE("nla_solver", tout << "k = " << k << ", c = "; print_factor_with_vars(c, tout); );
|
||||
|
||||
for (const factor & d : factors_with_the_same_abs_val(c)) {
|
||||
TRACE("nla_solver", tout << "d = "; print_factor_with_vars(d, tout); );
|
||||
|
@ -1687,7 +1707,7 @@ struct solver::imp {
|
|||
auto bkey = get_sorted_key_with_vars(b);
|
||||
SASSERT(akey.size() == bkey.size());
|
||||
for (unsigned i = 0; i < akey.size(); i++) {
|
||||
negate_abs_a_le_abs_b(a[i], b[i]);
|
||||
negate_abs_a_le_abs_b(akey[i].second, bkey[i].second);
|
||||
}
|
||||
assert_abs_val_a_le_abs_var_b(a, b, false);
|
||||
explain(a, current_expl());
|
||||
|
@ -2383,16 +2403,16 @@ void solver::test_basic_lemma_for_mon_zero_from_monomial_to_factors() {
|
|||
lp::lar_solver s;
|
||||
unsigned a = 0, b = 1, c = 2, d = 3, e = 4,
|
||||
abcde = 5, ac = 6, bde = 7, acd = 8, be = 9;
|
||||
lpvar lp_a = s.add_var(a, true);
|
||||
lpvar lp_b = s.add_var(b, true);
|
||||
lpvar lp_c = s.add_var(c, true);
|
||||
lpvar lp_d = s.add_var(d, true);
|
||||
lpvar lp_e = s.add_var(e, true);
|
||||
lpvar lp_abcde = s.add_var(abcde, true);
|
||||
lpvar lp_ac = s.add_var(ac, true);
|
||||
lpvar lp_bde = s.add_var(bde, true);
|
||||
lpvar lp_acd = s.add_var(acd, true);
|
||||
lpvar lp_be = s.add_var(be, true);
|
||||
lpvar lp_a = s.add_named_var(a, true, "a");
|
||||
lpvar lp_b = s.add_named_var(b, true, "b");
|
||||
lpvar lp_c = s.add_named_var(c, true, "c");
|
||||
lpvar lp_d = s.add_named_var(d, true, "d");
|
||||
lpvar lp_e = s.add_named_var(e, true, "e");
|
||||
lpvar lp_abcde = s.add_named_var(abcde, true, "abcde");
|
||||
lpvar lp_ac = s.add_named_var(ac, true, "ac");
|
||||
lpvar lp_bde = s.add_named_var(bde, true, "bde");
|
||||
lpvar lp_acd = s.add_named_var(acd, true, "acd");
|
||||
lpvar lp_be = s.add_named_var(be, true, "be");
|
||||
|
||||
reslimit l;
|
||||
params_ref p;
|
||||
|
@ -2412,10 +2432,17 @@ void solver::test_basic_lemma_for_mon_zero_from_monomial_to_factors() {
|
|||
vector<lemma> lemma;
|
||||
vector<lp::explanation> exp;
|
||||
|
||||
|
||||
|
||||
s.set_column_value(lp_a, rational(1));
|
||||
s.set_column_value(lp_b, rational(1));
|
||||
s.set_column_value(lp_d, rational(1));
|
||||
s.set_column_value(lp_c, rational(1));
|
||||
s.set_column_value(lp_e, rational(1));
|
||||
s.set_column_value(lp_e, rational(1));
|
||||
s.set_column_value(lp_abcde, rational(1));
|
||||
s.set_column_value(lp_ac, rational(1));
|
||||
s.set_column_value(lp_bde, rational(1));
|
||||
s.set_column_value(lp_acd, rational(1));
|
||||
s.set_column_value(lp_be, rational(1));
|
||||
|
||||
// set bde to zero
|
||||
s.set_column_value(lp_bde, rational(0));
|
||||
|
|
|
@ -30,78 +30,100 @@ struct index_with_sign {
|
|||
return m_i == b.m_i && m_sign == b.m_sign;
|
||||
}
|
||||
unsigned var() const { return m_i; }
|
||||
unsigned index() const { return m_i; }
|
||||
const rational& sign() const { return m_sign; }
|
||||
|
||||
};
|
||||
|
||||
struct rooted_mon {
|
||||
svector<lpvar> m_vars;
|
||||
index_with_sign m_orig;
|
||||
rooted_mon(const svector<lpvar>& vars, unsigned i, const rational& sign): m_vars(vars), m_orig(i, sign) {
|
||||
vector<index_with_sign> m_mons; // canonize_monomial(m_mons[j]) gives m_vector_of_rooted_monomials[m_i]
|
||||
|
||||
rooted_mon(const svector<lpvar>& vars, unsigned i, const rational& sign): m_vars(vars) {
|
||||
SASSERT(lp::is_non_decreasing(vars));
|
||||
push_back(index_with_sign(i, sign));
|
||||
}
|
||||
lpvar operator[](unsigned k) const { return m_vars[k];}
|
||||
unsigned size() const { return m_vars.size(); }
|
||||
unsigned orig_index() const { return m_orig.m_i; }
|
||||
const rational& orig_sign() const { return m_orig.m_sign; }
|
||||
unsigned orig_index() const { return m_mons.begin()->m_i; }
|
||||
const rational& orig_sign() const { return m_mons.begin()->m_sign; }
|
||||
const index_with_sign& orig() const { return *m_mons.begin(); }
|
||||
const svector<lpvar> & vars() const {return m_vars;}
|
||||
};
|
||||
|
||||
struct rooted_mon_info {
|
||||
unsigned m_i; // index to m_vector_of_rooted_monomials
|
||||
vector<index_with_sign> m_mons; // canonize_monomial(m_mons[j]) gives m_vector_of_rooted_monomials[m_i]
|
||||
rooted_mon_info(unsigned i, const index_with_sign& ind_s) : m_i(i) {
|
||||
m_mons.push_back(ind_s);
|
||||
}
|
||||
|
||||
void push_back(const index_with_sign& ind_s) {
|
||||
m_mons.push_back(ind_s);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct rooted_mon_table {
|
||||
std::unordered_map<svector<lpvar>,
|
||||
rooted_mon_info,
|
||||
hash_svector> m_rooted_monomials_map;
|
||||
vector<rooted_mon> m_vector_of_rooted_monomials;
|
||||
unsigned, // points to vec()
|
||||
hash_svector> m_map;
|
||||
vector<rooted_mon> m_vector;
|
||||
// for every k
|
||||
// for each i in m_rooted_monomials_containing_var[k]
|
||||
// m_vector_of_rooted_monomials[i] contains k
|
||||
std::unordered_map<lpvar, std::unordered_set<unsigned>> m_rooted_monomials_containing_var;
|
||||
std::unordered_map<lpvar, std::unordered_set<unsigned>> m_mons_containing_var;
|
||||
|
||||
// A map from m_vector_of_rooted_monomials to a set
|
||||
// of sets of m_vector_of_rooted_monomials,
|
||||
// such that for every i and every h in m_proper_factors[i]
|
||||
// m_vector_of_rooted_monomials[i] is a proper factor of m_vector_of_rooted_monomials[h]
|
||||
// such that for every i and every h in m_proper_factors[i] we have m_vector[i] as a proper factor of m_vector[h]
|
||||
std::unordered_map<unsigned, std::unordered_set<unsigned>> m_proper_factors;
|
||||
// points to m_vector
|
||||
svector<unsigned> m_to_refine;
|
||||
|
||||
void clear() {
|
||||
m_rooted_monomials_map.clear();
|
||||
m_vector_of_rooted_monomials.clear();
|
||||
m_rooted_monomials_containing_var.clear();
|
||||
m_proper_factors.clear();
|
||||
const svector<unsigned>& to_refine() { return m_to_refine; }
|
||||
|
||||
bool list_is_consistent(const vector<index_with_sign>& list, const std::unordered_set<unsigned>& to_refine_reg) const {
|
||||
bool t = to_refine_reg.find(list.begin()->index()) == to_refine_reg.end();
|
||||
for (const auto& i_s : list) {
|
||||
bool tt = to_refine_reg.find(i_s.index()) == to_refine_reg.end();
|
||||
if (tt != t) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool list_contains_to_refine_reg(const vector<index_with_sign>& list, const std::unordered_set<unsigned>& to_refine_reg) const {
|
||||
// the call should happen when no sign lemma is found, so the assert below should hold
|
||||
SASSERT(list_is_consistent(list, to_refine_reg));
|
||||
return !(to_refine_reg.find(list.begin()->index()) == to_refine_reg.end());
|
||||
}
|
||||
|
||||
const vector<rooted_mon>& vec() const { return m_vector_of_rooted_monomials; }
|
||||
vector<rooted_mon>& vec() { return m_vector_of_rooted_monomials; }
|
||||
void init_to_refine(const std::unordered_set<unsigned>& to_refine_reg) {
|
||||
for (unsigned i = 0; i < vec().size(); i++) {
|
||||
if (list_contains_to_refine_reg(vec()[i].m_mons, to_refine_reg))
|
||||
m_to_refine.push_back(i);
|
||||
}
|
||||
TRACE("nla_solver", tout << "rooted to_refine size = " << m_to_refine.size() << std::endl;);
|
||||
}
|
||||
|
||||
void clear() {
|
||||
m_map.clear();
|
||||
m_vector.clear();
|
||||
m_mons_containing_var.clear();
|
||||
m_proper_factors.clear();
|
||||
m_to_refine.clear();
|
||||
}
|
||||
|
||||
const vector<rooted_mon>& vec() const { return m_vector; }
|
||||
vector<rooted_mon>& vec() { return m_vector; }
|
||||
|
||||
const std::unordered_map<svector<lpvar>,
|
||||
rooted_mon_info,
|
||||
hash_svector> & map() const {
|
||||
return m_rooted_monomials_map;
|
||||
const std::unordered_map<svector<lpvar>, unsigned, hash_svector> & map() const {
|
||||
return m_map;
|
||||
}
|
||||
|
||||
std::unordered_map<svector<lpvar>,
|
||||
rooted_mon_info,
|
||||
hash_svector> & map() {
|
||||
return m_rooted_monomials_map;
|
||||
std::unordered_map<svector<lpvar>, unsigned, hash_svector> & map() {
|
||||
return m_map;
|
||||
}
|
||||
|
||||
const std::unordered_map<lpvar, std::unordered_set<unsigned>>& var_map() const {
|
||||
return m_rooted_monomials_containing_var;
|
||||
return m_mons_containing_var;
|
||||
}
|
||||
|
||||
std::unordered_map<lpvar, std::unordered_set<unsigned>>& var_map() {
|
||||
return m_rooted_monomials_containing_var;
|
||||
return m_mons_containing_var;
|
||||
}
|
||||
|
||||
std::unordered_map<unsigned, std::unordered_set<unsigned>>& proper_factors() {
|
||||
|
@ -126,7 +148,7 @@ struct rooted_mon_table {
|
|||
}
|
||||
}
|
||||
|
||||
// here i is the index of a monomial in m_vector_of_rooted_monomials
|
||||
// here i is the index of a monomial in m_vector
|
||||
void find_rooted_monomials_containing_rm(unsigned i_rm) {
|
||||
const auto & rm = vec()[i_rm];
|
||||
|
||||
|
@ -181,12 +203,11 @@ struct rooted_mon_table {
|
|||
auto it = map().find(mc.vars());
|
||||
if (it == map().end()) {
|
||||
TRACE("nla_solver", tout << "size = " << vec().size(););
|
||||
rooted_mon_info rmi(vec().size(), ms);
|
||||
map().emplace(mc.vars(), rmi);
|
||||
map().emplace(mc.vars(), vec().size());
|
||||
vec().push_back(rooted_mon(mc.vars(), i_mon, mc.coeff()));
|
||||
}
|
||||
else {
|
||||
it->second.push_back(ms);
|
||||
vec()[it->second].push_back(ms);
|
||||
TRACE("nla_solver", tout << "add ms.m_i = " << ms.m_i;);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue