mirror of
https://github.com/Z3Prover/z3
synced 2025-07-20 11:22:04 +00:00
toward order lemma
Signed-off-by: Lev <levnach@hotmail.com>
This commit is contained in:
parent
f211be1e49
commit
82589ad325
2 changed files with 116 additions and 55 deletions
|
@ -38,6 +38,7 @@ public:
|
||||||
unsigned& index() {return m_index;}
|
unsigned& index() {return m_index;}
|
||||||
factor_type type() const {return m_type;}
|
factor_type type() const {return m_type;}
|
||||||
factor_type& type() {return m_type;}
|
factor_type& type() {return m_type;}
|
||||||
|
bool is_var() const { return m_type == factor_type::VAR; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class factorization {
|
class factorization {
|
||||||
|
|
|
@ -90,6 +90,18 @@ struct solver::imp {
|
||||||
|
|
||||||
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.m_orig.m_i].var()) * rm.m_orig.m_sign; }
|
||||||
|
|
||||||
|
rational vvr(const factor& f) const { return f.is_var()? vvr(f.index()) : vvr(m_vector_of_rooted_monomials[f.index()]); }
|
||||||
|
|
||||||
|
lpvar var(const factor& f) const {
|
||||||
|
return f.is_var()?
|
||||||
|
f.index() : orig_mon_var(m_vector_of_rooted_monomials[f.index()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
rational flip_sign(const factor& f) const {
|
||||||
|
return f.is_var()?
|
||||||
|
rational(1) : m_vector_of_rooted_monomials[f.index()].m_orig.sign();
|
||||||
|
}
|
||||||
|
|
||||||
void add(lpvar v, unsigned sz, lpvar const* vs) {
|
void add(lpvar v, unsigned sz, lpvar const* vs) {
|
||||||
m_monomials.push_back(monomial(v, sz, vs));
|
m_monomials.push_back(monomial(v, sz, vs));
|
||||||
m_var_to_its_monomial.insert(v, m_monomials.size() - 1);
|
m_var_to_its_monomial.insert(v, m_monomials.size() - 1);
|
||||||
|
@ -480,9 +492,25 @@ struct solver::imp {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
std::ostream & print_factor(const factor& f, std::ostream& out) const {
|
||||||
|
if (f.is_var()) {
|
||||||
|
print_var(f.index(), out);
|
||||||
|
} else {
|
||||||
|
print_product(m_vector_of_rooted_monomials[f.index()].vars(), out);
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
std::ostream & print_factorization(const factorization& f, std::ostream& out) const {
|
std::ostream & print_factorization(const factorization& f, std::ostream& out) const {
|
||||||
for (unsigned k = 0; k < f.size(); k++ ) {
|
for (unsigned k = 0; k < f.size(); k++ ) {
|
||||||
print_var(f[k], out);
|
if (f[k].is_var())
|
||||||
|
print_var(f[k].index(), out);
|
||||||
|
else {
|
||||||
|
print_product(m_vector_of_rooted_monomials[f[k].index()].vars(), out);
|
||||||
|
}
|
||||||
if (k < f.size() - 1)
|
if (k < f.size() - 1)
|
||||||
out << "*";
|
out << "*";
|
||||||
}
|
}
|
||||||
|
@ -496,15 +524,13 @@ struct solver::imp {
|
||||||
factorization_factory(m_vars),
|
factorization_factory(m_vars),
|
||||||
m_imp(s) { }
|
m_imp(s) { }
|
||||||
|
|
||||||
bool find_monomial_of_vars(const svector<lpvar>& vars, monomial& m, rational & sign) const {
|
bool find_monomial_of_vars(const svector<lpvar>& vars, unsigned & i) const {
|
||||||
auto it = m_imp.m_rooted_monomials_map.find(vars);
|
auto it = m_imp.m_rooted_monomials_map.find(vars);
|
||||||
if (it == m_imp.m_rooted_monomials_map.end()) {
|
if (it == m_imp.m_rooted_monomials_map.end()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const index_with_sign & mi = *(it->second.begin());
|
i = it->second.begin()->m_i;
|
||||||
sign = mi.m_sign;
|
|
||||||
m = m_imp.m_monomials[mi.m_i];
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -518,7 +544,7 @@ struct solver::imp {
|
||||||
bool basic_lemma_for_mon_zero(const rooted_mon& rm, const factorization& f) {
|
bool basic_lemma_for_mon_zero(const rooted_mon& rm, const factorization& f) {
|
||||||
TRACE("nla_solver", trace_print_monomial_and_factorization(rm, f, tout););
|
TRACE("nla_solver", trace_print_monomial_and_factorization(rm, f, tout););
|
||||||
SASSERT(vvr(rm).is_zero());
|
SASSERT(vvr(rm).is_zero());
|
||||||
for (lpvar j : f) {
|
for (auto j : f) {
|
||||||
if (vvr(j).is_zero()) {
|
if (vvr(j).is_zero()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -527,8 +553,8 @@ struct solver::imp {
|
||||||
SASSERT(m_lemma->empty());
|
SASSERT(m_lemma->empty());
|
||||||
|
|
||||||
mk_ineq(orig_mon_var(rm), lp::lconstraint_kind::NE);
|
mk_ineq(orig_mon_var(rm), lp::lconstraint_kind::NE);
|
||||||
for (lpvar j : f) {
|
for (auto j : f) {
|
||||||
mk_ineq(j, lp::lconstraint_kind::EQ);
|
mk_ineq(var(j), lp::lconstraint_kind::EQ);
|
||||||
}
|
}
|
||||||
|
|
||||||
explain(rm);
|
explain(rm);
|
||||||
|
@ -562,9 +588,9 @@ struct solver::imp {
|
||||||
TRACE("nla_solver", trace_print_monomial_and_factorization(rm, f, tout););
|
TRACE("nla_solver", 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;
|
||||||
for (lpvar j : f) {
|
for (auto j : f) {
|
||||||
if (vvr(j).is_zero()) {
|
if (vvr(j).is_zero()) {
|
||||||
zero_j = j;
|
zero_j = var(j);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -574,7 +600,7 @@ struct solver::imp {
|
||||||
}
|
}
|
||||||
|
|
||||||
mk_ineq(zero_j, lp::lconstraint_kind::NE);
|
mk_ineq(zero_j, lp::lconstraint_kind::NE);
|
||||||
mk_ineq(m_monomials[rm.orig_index()].var(), lp::lconstraint_kind::EQ);
|
mk_ineq(orig_mon_var(rm), lp::lconstraint_kind::EQ);
|
||||||
|
|
||||||
explain(rm);
|
explain(rm);
|
||||||
TRACE("nla_solver", print_lemma(tout););
|
TRACE("nla_solver", print_lemma(tout););
|
||||||
|
@ -596,21 +622,21 @@ struct solver::imp {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
lpvar jl = -1;
|
lpvar jl = -1;
|
||||||
for (lpvar j : f ) {
|
for (auto j : f ) {
|
||||||
if (abs(vvr(j)) == abs_mv) {
|
if (abs(vvr(j)) == abs_mv) {
|
||||||
jl = j;
|
jl = var(j);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (jl == static_cast<lpvar>(-1))
|
if (jl == static_cast<lpvar>(-1))
|
||||||
return false;
|
return false;
|
||||||
lpvar not_one_j = -1;
|
lpvar not_one_j = -1;
|
||||||
for (lpvar j : f ) {
|
for (auto j : f ) {
|
||||||
if (j == jl) {
|
if (var(j) == jl) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (abs(vvr(j)) != rational(1)) {
|
if (abs(vvr(j)) != rational(1)) {
|
||||||
not_one_j = j;
|
not_one_j = var(j);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -640,8 +666,8 @@ struct solver::imp {
|
||||||
// 1 * 1 ... * 1 * x * 1 ... * 1 = x
|
// 1 * 1 ... * 1 * x * 1 ... * 1 = x
|
||||||
bool basic_lemma_for_mon_neutral_from_factors_to_monomial(const rooted_mon& rm, const factorization& f) {
|
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.m_orig.m_sign;
|
||||||
lpvar not_one_j = -1;
|
lpvar not_one = -1;
|
||||||
for (lpvar j : f){
|
for (auto j : f){
|
||||||
if (vvr(j) == rational(1)) {
|
if (vvr(j) == rational(1)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -651,8 +677,8 @@ struct solver::imp {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (not_one_j == static_cast<lpvar>(-1)) {
|
if (not_one == static_cast<lpvar>(-1)) {
|
||||||
not_one_j = j;
|
not_one = var(j);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -662,18 +688,16 @@ struct solver::imp {
|
||||||
|
|
||||||
explain(rm);
|
explain(rm);
|
||||||
|
|
||||||
for (lpvar j : f){
|
for (auto j : f){
|
||||||
if (vvr(j) == rational(1)) {
|
lpvar var_j = var(j);
|
||||||
mk_ineq(j, lp::lconstraint_kind::NE, rational(1));
|
if (not_one == var_j) continue;
|
||||||
} else if (vvr(j) == -rational(1)) {
|
mk_ineq(var_j, lp::lconstraint_kind::NE, j.is_var()? vvr(j) : flip_sign(j) * vvr(j) );
|
||||||
mk_ineq(j, lp::lconstraint_kind::NE, -rational(1));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (not_one_j == static_cast<lpvar>(-1)) {
|
if (not_one == static_cast<lpvar>(-1)) {
|
||||||
mk_ineq(m_monomials[rm.orig_index()].var(), lp::lconstraint_kind::EQ, rational(sign));
|
mk_ineq(m_monomials[rm.orig_index()].var(), lp::lconstraint_kind::EQ, sign);
|
||||||
} else {
|
} else {
|
||||||
mk_ineq(m_monomials[rm.orig_index()].var(), -rational(sign), not_one_j, lp::lconstraint_kind::EQ);
|
mk_ineq(m_monomials[rm.orig_index()].var(), -sign, not_one, lp::lconstraint_kind::EQ);
|
||||||
}
|
}
|
||||||
TRACE("nla_solver", print_lemma(tout););
|
TRACE("nla_solver", print_lemma(tout););
|
||||||
return true;
|
return true;
|
||||||
|
@ -896,11 +920,32 @@ struct solver::imp {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void register_monomial_containing_vars(unsigned i) {
|
||||||
|
for (lpvar j : m_vector_of_rooted_monomials[i].vars()) {
|
||||||
|
auto it = m_rooted_monomials_containing_var.find(j);
|
||||||
|
if (it == m_rooted_monomials_containing_var.end()) {
|
||||||
|
std::unordered_set<unsigned> s;
|
||||||
|
s.insert(i);
|
||||||
|
m_rooted_monomials_containing_var[i] = s;
|
||||||
|
} else {
|
||||||
|
it->second.insert(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void fill_rooted_monomials_containing_var() {
|
||||||
|
for (unsigned i = 0; i < m_vector_of_rooted_monomials.size(); i++) {
|
||||||
|
register_monomial_containing_vars(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void register_monomials_in_tables() {
|
void register_monomials_in_tables() {
|
||||||
m_vars_equivalence.clear_monomials_by_abs_vals();
|
m_vars_equivalence.clear_monomials_by_abs_vals();
|
||||||
for (unsigned i = 0; i < m_monomials.size(); i++)
|
for (unsigned i = 0; i < m_monomials.size(); i++)
|
||||||
register_monomial_in_tables(i);
|
register_monomial_in_tables(i);
|
||||||
|
|
||||||
|
fill_rooted_monomials_containing_var();
|
||||||
fill_rooted_factor_to_product();
|
fill_rooted_factor_to_product();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -923,6 +968,7 @@ struct solver::imp {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool order_lemma_on_ac_and_bc(const rooted_mon& rm, const factorization& ac, unsigned k, const rooted_mon& rm_bc) {
|
bool order_lemma_on_ac_and_bc(const rooted_mon& rm, const factorization& ac, unsigned k, const rooted_mon& rm_bc) {
|
||||||
|
NOT_IMPLEMENTED_YET();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -930,14 +976,28 @@ struct solver::imp {
|
||||||
// ac is a factorization of m_monomials[i_mon]
|
// ac is a factorization of m_monomials[i_mon]
|
||||||
// ac[k] plays the role of c
|
// ac[k] plays the role of c
|
||||||
bool order_lemma_on_factor(const rooted_mon& rm, const factorization& ac, unsigned k) {
|
bool order_lemma_on_factor(const rooted_mon& rm, const factorization& ac, unsigned k) {
|
||||||
lpvar c = ac[k];
|
auto c = ac[k];
|
||||||
TRACE("nla_solver", tout << "k = " << k << ", c = " << c; );
|
TRACE("nla_solver", tout << "k = " << k << ", c = "; print_factor(c, tout); );
|
||||||
SASSERT(m_rooted_monomials_containing_var.find(c) != m_rooted_monomials_containing_var.end());
|
|
||||||
for (unsigned rm_bc : m_rooted_monomials_containing_var[c]) {
|
if (c.is_var()) {
|
||||||
|
TRACE("nla_solver", );
|
||||||
|
|
||||||
|
for (unsigned rm_bc : m_rooted_monomials_containing_var[var(c)]) {
|
||||||
|
TRACE("nla_solver", );
|
||||||
if (order_lemma_on_ac_and_bc(rm , ac, k, m_vector_of_rooted_monomials[rm_bc])) {
|
if (order_lemma_on_ac_and_bc(rm , ac, k, m_vector_of_rooted_monomials[rm_bc])) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
TRACE("nla_solver", );
|
||||||
|
for (unsigned rm_bc : m_rooted_factor_to_product[var(c)]) {
|
||||||
|
TRACE("nla_solver", );
|
||||||
|
if (order_lemma_on_ac_and_bc(rm , ac, k, m_vector_of_rooted_monomials[rm_bc])) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1072,8 +1132,8 @@ struct solver::imp {
|
||||||
for (auto f : fc) {
|
for (auto f : fc) {
|
||||||
if (f.is_empty()) continue;
|
if (f.is_empty()) continue;
|
||||||
found_factorizations ++;
|
found_factorizations ++;
|
||||||
for (lpvar j : f) {
|
for (auto j : f) {
|
||||||
std::cout << "j = "; print_var(j, std::cout);
|
std::cout << "j = "; print_factor(j, std::cout);
|
||||||
}
|
}
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue