3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-06-23 06:13:40 +00:00

towards full factorizations on a monomial

This commit is contained in:
Lev Nachmanson 2019-03-25 15:43:12 -07:00
parent 1810d7e77d
commit 90bda39aef
3 changed files with 106 additions and 47 deletions

View file

@ -51,11 +51,11 @@ bool const_iterator_mon::get_factors(factor& k, factor& j, rational& sign) const
factorization const_iterator_mon::operator*() const { factorization const_iterator_mon::operator*() const {
if (m_full_factorization_returned == false) { if (m_full_factorization_returned == false) {
return create_full_factorization(); return create_full_factorization(m_ff->m_monomial);
} }
factor j, k; rational sign; factor j, k; rational sign;
if (!get_factors(j, k, sign)) if (!get_factors(j, k, sign))
return factorization(); return factorization(nullptr);
return create_binary_factorization(j, k); return create_binary_factorization(j, k);
} }
@ -82,7 +82,7 @@ const_iterator_mon::self_type const_iterator_mon::operator++(int) { advance_mask
const_iterator_mon::const_iterator_mon(const svector<bool>& mask, const factorization_factory *f) : const_iterator_mon::const_iterator_mon(const svector<bool>& mask, const factorization_factory *f) :
m_mask(mask), m_mask(mask),
m_ff(f) , m_ff(f) ,
m_full_factorization_returned(mask.size() == 1) // if mask.size() is equal to 1 the full factorization is not needed m_full_factorization_returned(false)
{} {}
bool const_iterator_mon::operator==(const const_iterator_mon::self_type &other) const { bool const_iterator_mon::operator==(const const_iterator_mon::self_type &other) const {
@ -106,19 +106,21 @@ factorization const_iterator_mon::create_binary_factorization(factor j, factor k
// impl.add_explanation_of_reducing_to_rooted_monomial(m_ff->m_mon, exp); // impl.add_explanation_of_reducing_to_rooted_monomial(m_ff->m_mon, exp);
// }; // };
factorization f; factorization f(nullptr);
f.push_back(j); f.push_back(j);
f.push_back(k); f.push_back(k);
return f; return f;
} }
factorization const_iterator_mon::create_full_factorization() const { factorization const_iterator_mon::create_full_factorization(const monomial* m) const {
factorization f; if (m != nullptr)
// f.vars() = m_ff->m_vars; return factorization(m);
factorization f(nullptr);
for (lpvar j : m_ff->m_vars) { for (lpvar j : m_ff->m_vars) {
f.push_back(factor(j, factor_type::VAR)); f.push_back(factor(j, factor_type::VAR));
} }
return f; return f;
} }
} }

View file

@ -54,14 +54,25 @@ inline bool operator!=(const factor& a, const factor& b) {
class factorization { class factorization {
vector<factor> m_vars; vector<factor> m_vars;
const monomial* m_mon;
public: public:
factorization(const monomial* m): m_mon(m) {
if (m != nullptr) {
for(lpvar j : *m)
m_vars.push_back(factor(j, factor_type::VAR));
}
}
bool is_mon() const { return m_mon != nullptr;}
bool is_empty() const { return m_vars.empty(); } bool is_empty() const { return m_vars.empty(); }
const vector<factor> & vars() const { return m_vars; }
factor operator[](unsigned k) const { return m_vars[k]; } factor operator[](unsigned k) const { return m_vars[k]; }
size_t size() const { return m_vars.size(); } size_t size() const { return m_vars.size(); }
const factor* begin() const { return m_vars.begin(); } const factor* begin() const { return m_vars.begin(); }
const factor* end() const { return m_vars.end(); } const factor* end() const { return m_vars.end(); }
void push_back(factor v) {m_vars.push_back(v);} void push_back(factor v) {
SASSERT(!is_mon());
m_vars.push_back(v);
}
const monomial* mon() const { return m_mon; }
}; };
struct const_iterator_mon { struct const_iterator_mon {
@ -93,23 +104,34 @@ struct const_iterator_mon {
factorization create_binary_factorization(factor j, factor k) const; factorization create_binary_factorization(factor j, factor k) const;
factorization create_full_factorization() const; factorization create_full_factorization(const monomial*) const;
}; };
struct factorization_factory { struct factorization_factory {
const svector<lpvar>& m_vars; const svector<lpvar>& m_vars;
const monomial* m_monomial;
// returns true if found // returns true if found
virtual bool find_rm_monomial_of_vars(const svector<lpvar>& vars, unsigned& i) const = 0; virtual bool find_rm_monomial_of_vars(const svector<lpvar>& vars, unsigned& i) const = 0;
virtual const monomial* find_monomial_of_vars(const svector<lpvar>& vars) const = 0;
factorization_factory(const svector<lpvar>& vars) :
m_vars(vars) { factorization_factory(const svector<lpvar>& vars, const monomial* m) :
m_vars(vars), m_monomial(m) {
}
svector<bool> get_mask() const {
// we keep the last element always in the first factor to avoid
// repeating a pair twice, that is why m_mask is shorter by one then m_vars
return
m_vars.size() != 2?
svector<bool>(m_vars.size() - 1, false)
:
svector<bool>(1, true); // init mask as in the end() since the full iteration will do the job
} }
const_iterator_mon begin() const { const_iterator_mon begin() const {
// we keep the last element always in the first factor to avoid return const_iterator_mon(get_mask(), this);
// repeating a pair twice
svector<bool> mask(m_vars.size() - 1, false);
return const_iterator_mon(mask, this);
} }
const_iterator_mon end() const { const_iterator_mon end() const {

View file

@ -1060,16 +1060,29 @@ struct solver::imp {
return true; return true;
} }
const monomial* find_monomial_of_vars(const svector<lpvar>& vars) const {
unsigned i;
if (!find_rm_monomial_of_vars(vars, i))
return nullptr;
return &m_monomials[m_rm_table.rms()[i].orig_index()];
}
struct factorization_factory_imp: factorization_factory { struct factorization_factory_imp: factorization_factory {
const imp& m_imp; const imp& m_imp;
const monomial *m_mon;
const rooted_mon& m_rm;
factorization_factory_imp(const svector<lpvar>& m_vars, const imp& s) : factorization_factory_imp(const rooted_mon& rm, const imp& s) :
factorization_factory(m_vars), factorization_factory(rm.m_vars, &s.m_monomials[rm.orig_index()]),
m_imp(s) { } m_imp(s), m_mon(& s.m_monomials[rm.orig_index()]), m_rm(rm) { }
bool find_rm_monomial_of_vars(const svector<lpvar>& vars, unsigned & i) const { bool find_rm_monomial_of_vars(const svector<lpvar>& vars, unsigned & i) const {
return m_imp.find_rm_monomial_of_vars(vars, i); return m_imp.find_rm_monomial_of_vars(vars, i);
} }
const monomial* find_monomial_of_vars(const svector<lpvar>& vars) const {
return m_imp.find_monomial_of_vars(vars);
}
}; };
// here we use the fact // here we use the fact
// xy = 0 -> x = 0 or y = 0 // xy = 0 -> x = 0 or y = 0
@ -1163,7 +1176,15 @@ struct solver::imp {
current_expl().add(m_lar_solver.get_column_lower_bound_witness(j)); current_expl().add(m_lar_solver.get_column_lower_bound_witness(j));
} }
// x = 0 or y = 0 -> xy = 0 // x = 0 or y = 0 -> xy = 0
bool basic_lemma_for_mon_non_zero_model_based(const rooted_mon& rm, const factorization& f) { void basic_lemma_for_mon_non_zero_model_based(const rooted_mon& rm, const factorization& f) {
TRACE("nla_solver_bl", trace_print_monomial_and_factorization(rm, f, tout););
if (f.is_mon())
basic_lemma_for_mon_non_zero_model_based_mf(f);
else
basic_lemma_for_mon_non_zero_model_based_mf(f);
}
// x = 0 or y = 0 -> xy = 0
void basic_lemma_for_mon_non_zero_model_based_rm(const rooted_mon& rm, const factorization& f) {
TRACE("nla_solver_bl", trace_print_monomial_and_factorization(rm, f, tout);); TRACE("nla_solver_bl", trace_print_monomial_and_factorization(rm, f, tout););
SASSERT (!vvr(rm).is_zero()); SASSERT (!vvr(rm).is_zero());
int zero_j = -1; int zero_j = -1;
@ -1174,16 +1195,30 @@ struct solver::imp {
} }
} }
if (zero_j == -1) { if (zero_j == -1) { return; }
return false;
}
add_empty_lemma(); add_empty_lemma();
mk_ineq(zero_j, llc::NE); mk_ineq(zero_j, llc::NE);
mk_ineq(var(rm), llc::EQ); mk_ineq(var(rm), llc::EQ);
explain(rm, current_expl()); explain(rm, current_expl());
explain(f, current_expl());
TRACE("nla_solver", print_lemma(tout););
}
void basic_lemma_for_mon_non_zero_model_based_mf(const factorization& f) {
TRACE("nla_solver_bl", print_factorization(f, tout););
int zero_j = -1;
for (auto j : f) {
if (vvr(j).is_zero()) {
zero_j = var(j);
break;
}
}
if (zero_j == -1) { return; }
add_empty_lemma();
mk_ineq(zero_j, llc::NE);
mk_ineq(f.mon()->var(), llc::EQ);
TRACE("nla_solver", print_lemma(tout);); TRACE("nla_solver", print_lemma(tout););
return true;
} }
bool var_has_positive_lower_bound(lpvar j) const { bool var_has_positive_lower_bound(lpvar j) const {
@ -1579,14 +1614,14 @@ struct solver::imp {
void basic_lemma_for_mon_model_based(const rooted_mon& rm) { void basic_lemma_for_mon_model_based(const rooted_mon& rm) {
TRACE("nla_solver_bl", tout << "rm = "; print_rooted_monomial(rm, tout);); TRACE("nla_solver_bl", tout << "rm = "; print_rooted_monomial(rm, tout););
if (vvr(rm).is_zero()) { if (vvr(rm).is_zero()) {
for (auto factorization : factorization_factory_imp(rm.m_vars, *this)) { for (auto factorization : factorization_factory_imp(rm, *this)) {
if (factorization.is_empty()) if (factorization.is_empty())
continue; continue;
basic_lemma_for_mon_zero_model_based(rm, factorization); basic_lemma_for_mon_zero_model_based(rm, factorization);
basic_lemma_for_mon_neutral_model_based(rm, factorization); basic_lemma_for_mon_neutral_model_based(rm, factorization);
} }
} else { } else {
for (auto factorization : factorization_factory_imp(rm.m_vars, *this)) { for (auto factorization : factorization_factory_imp(rm, *this)) {
if (factorization.is_empty()) if (factorization.is_empty())
continue; continue;
basic_lemma_for_mon_non_zero_model_based(rm, factorization); basic_lemma_for_mon_non_zero_model_based(rm, factorization);
@ -1598,7 +1633,7 @@ struct solver::imp {
bool basic_lemma_for_mon_derived(const rooted_mon& rm) { bool basic_lemma_for_mon_derived(const rooted_mon& rm) {
if (var_is_fixed_to_zero(var(rm))) { if (var_is_fixed_to_zero(var(rm))) {
for (auto factorization : factorization_factory_imp(rm.m_vars, *this)) { for (auto factorization : factorization_factory_imp(rm, *this)) {
if (factorization.is_empty()) if (factorization.is_empty())
continue; continue;
if (basic_lemma_for_mon_zero(rm, factorization) || if (basic_lemma_for_mon_zero(rm, factorization) ||
@ -1608,7 +1643,7 @@ struct solver::imp {
} }
} }
} else { } else {
for (auto factorization : factorization_factory_imp(rm.m_vars, *this)) { for (auto factorization : factorization_factory_imp(rm, *this)) {
if (factorization.is_empty()) if (factorization.is_empty())
continue; continue;
if (basic_lemma_for_mon_non_zero_derived(rm, factorization) || if (basic_lemma_for_mon_non_zero_derived(rm, factorization) ||
@ -2260,7 +2295,7 @@ struct solver::imp {
tout << "rm = "; print_product(rm, tout); tout << "rm = "; print_product(rm, tout);
tout << ", orig = "; print_monomial(m_monomials[rm.orig_index()], tout); tout << ", orig = "; print_monomial(m_monomials[rm.orig_index()], tout);
); );
for (auto ac : factorization_factory_imp(rm.vars(), *this)) { for (auto ac : factorization_factory_imp(rm, *this)) {
if (ac.size() != 2) if (ac.size() != 2)
continue; continue;
order_lemma_on_factorization(rm, ac); order_lemma_on_factorization(rm, ac);
@ -2599,7 +2634,7 @@ struct solver::imp {
} }
bool find_bfc_on_monomial(const rooted_mon& rm, bfc & bf) { bool find_bfc_on_monomial(const rooted_mon& rm, bfc & bf) {
for (auto factorization : factorization_factory_imp(rm.m_vars, *this)) { for (auto factorization : factorization_factory_imp(rm, *this)) {
if (factorization.size() == 2) { if (factorization.size() == 2) {
lpvar a = var(factorization[0]); lpvar a = var(factorization[0]);
lpvar b = var(factorization[1]); lpvar b = var(factorization[1]);
@ -2924,23 +2959,23 @@ struct solver::imp {
return true; return true;
} }
void test_factorization(unsigned mon_index, unsigned number_of_factorizations) { void test_factorization(unsigned /*mon_index*/, unsigned /*number_of_factorizations*/) {
vector<ineq> lemma; // vector<ineq> lemma;
unsigned_vector vars = m_monomials[mon_index].vars(); // unsigned_vector vars = m_monomials[mon_index].vars();
factorization_factory_imp fc(vars, // 0 is the index of "abcde" // factorization_factory_imp fc(vars, // 0 is the index of "abcde"
*this); // *this);
std::cout << "factorizations = of "; print_monomial(m_monomials[mon_index], std::cout) << "\n"; // std::cout << "factorizations = of "; print_monomial(m_monomials[mon_index], std::cout) << "\n";
unsigned found_factorizations = 0; // unsigned found_factorizations = 0;
for (auto f : fc) { // for (auto f : fc) {
if (f.is_empty()) continue; // if (f.is_empty()) continue;
found_factorizations ++; // found_factorizations ++;
print_factorization(f, std::cout); // print_factorization(f, std::cout);
std::cout << std::endl; // std::cout << std::endl;
} // }
SASSERT(found_factorizations == number_of_factorizations); // SASSERT(found_factorizations == number_of_factorizations);
} }
lbool test_check( lbool test_check(