3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-23 17:15:31 +00:00

adding pre-processing to nlsat for equations

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2017-12-30 20:35:33 -08:00
parent 5bc4c9809e
commit 79a9dfd8fd
11 changed files with 696 additions and 222 deletions

View file

@ -150,7 +150,6 @@ namespace polynomial {
return r;
}
/**
\brief Monomials (power products)
*/
@ -192,7 +191,7 @@ namespace polynomial {
};
static unsigned get_obj_size(unsigned sz) { return sizeof(monomial) + sz * sizeof(power); }
monomial(unsigned id, unsigned sz, power const * pws, unsigned h):
m_ref_count(0),
m_id(id),
@ -257,9 +256,7 @@ namespace polynomial {
if (m_size < SMALL_MONOMIAL) {
// use linear search for small monomials
// search backwards since we usually ask for the degree of "big" variables
unsigned i = last;
while (i > 0) {
--i;
for (unsigned i = last; i-- > 0; ) {
if (get_var(i) == x)
return i;
}
@ -798,9 +795,8 @@ namespace polynomial {
dec_ref(m_unit);
CTRACE("polynomial", !m_monomials.empty(),
tout << "monomials leaked\n";
monomial_table::iterator it = m_monomials.begin(); monomial_table::iterator end = m_monomials.end();
for (; it != end; ++it) {
(*it)->display(tout); tout << "\n";
for (auto * m : m_monomials) {
m->display(tout); tout << "\n";
});
SASSERT(m_monomials.empty());
if (m_own_allocator)
@ -1510,6 +1506,8 @@ namespace polynomial {
unsigned id() const { return m_id; }
unsigned size() const { return m_size; }
monomial * m(unsigned idx) const { SASSERT(idx < size()); return m_ms[idx]; }
monomial *const* begin() const { return m_ms; }
monomial *const* end() const { return m_ms + size(); }
numeral const & a(unsigned idx) const { SASSERT(idx < size()); return m_as[idx]; }
numeral & a(unsigned idx) { SASSERT(idx < size()); return m_as[idx]; }
numeral const * as() const { return m_as; }
@ -1773,11 +1771,9 @@ namespace polynomial {
}
bool manager::is_linear(polynomial const * p) {
unsigned sz = p->size();
for (unsigned i = 0; i < sz; i++) {
if (!is_linear(p->m(0)))
for (monomial* m : *p)
if (!is_linear(m))
return false;
}
return true;
}
@ -2396,6 +2392,7 @@ namespace polynomial {
return mm().is_valid(x);
}
void add_del_eh(del_eh * eh) {
eh->m_next = m_del_eh;
m_del_eh = eh;
@ -6101,6 +6098,33 @@ namespace polynomial {
});
}
lbool sign(monomial* m, numeral const& c, svector<lbool> const& sign_of_vars) {
unsigned sz = size(m);
lbool sign1 = m_manager.is_pos(c) ? l_true : l_false;
for (unsigned i = 0; i < sz; ++i) {
var v = get_var(m, i);
unsigned d = degree(m, i);
lbool sign2 = sign_of_vars.get(v, l_undef);
if (sign2 == l_undef)
return l_undef;
else if (1 == (d % 2) && sign2 == l_false) {
sign1 = sign1 == l_true ? l_false : l_true;
}
}
return sign1;
}
lbool sign(polynomial const * p, svector<lbool> const& sign_of_vars) {
unsigned sz = size(p);
if (sz == 0) return l_undef;
lbool sign1 = sign(p->m(0), p->a(0), sign_of_vars);
for (unsigned i = 1; sign1 != l_undef && i < sz; ++i) {
if (sign(p->m(i), p->a(i), sign_of_vars) != sign1)
return l_undef;
}
return sign1;
}
bool is_pos(polynomial const * p) {
bool found_unit = false;
unsigned sz = p->size();
@ -6372,6 +6396,31 @@ namespace polynomial {
R.add(new_a, mk_monomial(new_m));
}
return R.mk();
}
void substitute(polynomial const* r, var x, polynomial const* p, polynomial const* q, polynomial_ref& result) {
unsigned md = degree(r, x);
if (md == 0) {
result = const_cast<polynomial*>(r);
return;
}
result = 0;
polynomial_ref p1(pm()), q1(pm());
polynomial_ref_buffer ps(pm());
unsigned sz = r->size();
for (unsigned i = 0; i < sz; i++) {
monomial * m0 = r->m(i);
unsigned dm = m0->degree_of(x);
SASSERT(md >= dm);
monomial_ref m1(div_x(m0, x), pm());
pw(p, dm, p1);
pw(q, md - dm, q1);
p1 = mul(r->a(i), m1, p1 * q1);
if (result)
result = add(result, p1);
else
result = p1;
}
}
@ -6918,6 +6967,18 @@ namespace polynomial {
return m_imp->m().set_zp(p);
}
bool manager::is_var(polynomial const* p, var& v) {
return p->size() == 1 && is_var(p->m(0), v) && m_imp->m().is_one(p->a(0));
}
bool manager::is_var(monomial const* m, var& v) {
return m->size() == 1 && m->degree(0) == 1 && (v = m->get_var(0), true);
}
bool manager::is_var_num(polynomial const* p, var& v, scoped_numeral& n) {
return p->size() == 2 && m_imp->m().is_one(p->a(0)) && is_var(p->m(0), v) && is_unit(p->m(1)) && (n = p->a(1), true);
}
small_object_allocator & manager::allocator() const {
return m_imp->mm().allocator();
}
@ -7271,6 +7332,10 @@ namespace polynomial {
void manager::psc_chain(polynomial const * p, polynomial const * q, var x, polynomial_ref_vector & S) {
m_imp->psc_chain(p, q, x, S);
}
lbool manager::sign(polynomial const * p, svector<lbool> const& sign_of_vars) {
return m_imp->sign(p, sign_of_vars);
}
bool manager::is_pos(polynomial const * p) {
return m_imp->is_pos(p);
@ -7307,6 +7372,10 @@ namespace polynomial {
polynomial * manager::substitute(polynomial const * p, unsigned xs_sz, var const * xs, numeral const * vs) {
return m_imp->substitute(p, xs_sz, xs, vs);
}
void manager::substitute(polynomial const* r, var x, polynomial const* p, polynomial const* q, polynomial_ref& result) {
m_imp->substitute(r, x, p, q, result);
}
void manager::factor(polynomial const * p, factors & r, factor_params const & params) {
m_imp->factor(p, r, params);

View file

@ -29,6 +29,7 @@ Notes:
#include "util/params.h"
#include "util/mpbqi.h"
#include "util/rlimit.h"
#include "util/lbool.h"
class small_object_allocator;
@ -98,7 +99,7 @@ namespace polynomial {
};
struct display_var_proc {
virtual void operator()(std::ostream & out, var x) const { out << "x" << x; }
virtual std::ostream& operator()(std::ostream & out, var x) const { return out << "x" << x; }
};
class polynomial;
@ -306,12 +307,27 @@ namespace polynomial {
\brief Return true if m is linear (i.e., it is of the form 1 or x).
*/
static bool is_linear(monomial const * m);
/**
\brief Return true if all monomials in p are linear.
*/
static bool is_linear(polynomial const * p);
/**
\brief Return true if the monomial is a variable.
*/
static bool is_var(monomial const* p, var& v);
/**
\brief Return true if the polynomial is a variable.
*/
bool is_var(polynomial const* p, var& v);
/**
\brief Return true if the polynomial is of the form x + k
*/
bool is_var_num(polynomial const* p, var& v, scoped_numeral& n);
/**
\brief Return the degree of variable x in p.
*/
@ -860,7 +876,13 @@ namespace polynomial {
\brief Return true if p is a square, and store its square root in r.
*/
bool sqrt(polynomial const * p, polynomial_ref & r);
/**
\brief obtain the sign of the polynomial given sign of variables.
*/
lbool sign(polynomial const* p, svector<lbool> const& sign_of_vars);
/**
\brief Return true if p is always positive for any assignment of its variables.
@ -936,6 +958,13 @@ namespace polynomial {
return substitute(p, 1, &x, &v);
}
/**
\brief Apply substiution [x -> p/q] in r.
That is, given r \in Z[x, y_1, .., y_m] return
polynomial q^k * r(p/q, y_1, .., y_m), where k is the maximal degree of x in r.
*/
void substitute(polynomial const* r, var x, polynomial const* p, polynomial const* q, polynomial_ref& result);
/**
\brief Factorize the given polynomial p and store its factors in r.
*/