mirror of
https://github.com/Z3Prover/z3
synced 2025-08-05 19:00:25 +00:00
Nlsat simplify (#7227)
* dev branch for simplification Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * bug fixes Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * bugfixes Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * fix factorization Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * separate out simplification functionality * reorder initialization Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * reorder initialization Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * Update README.md * initial warppers for seq-map/seq-fold Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * expose fold as well Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * add C++ bindings for sequence operations Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * add abs function to API Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * add parameter validation to ternary and 4-ary functions for API #7219 Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * add pre-processing and reorder Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * add pre-processing and reorder Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> --------- Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
e036a5bd9b
commit
8fe357f1f2
13 changed files with 1275 additions and 844 deletions
|
@ -2594,27 +2594,28 @@ namespace algebraic_numbers {
|
|||
|
||||
void int_lt(numeral const & a, numeral & b) {
|
||||
scoped_mpz v(qm());
|
||||
if (!a.is_basic())
|
||||
refine_until_prec(const_cast<numeral&>(a), 1);
|
||||
if (a.is_basic()) {
|
||||
qm().floor(basic_value(a), v);
|
||||
qm().dec(v);
|
||||
}
|
||||
else {
|
||||
refine_until_prec(const_cast<numeral&>(a), 1);
|
||||
bqm().floor(qm(), lower(a.to_algebraic()), v);
|
||||
}
|
||||
else
|
||||
bqm().floor(qm(), lower(a.to_algebraic()), v);
|
||||
m_wrapper.set(b, v);
|
||||
}
|
||||
|
||||
void int_gt(numeral const & a, numeral & b) {
|
||||
scoped_mpz v(qm());
|
||||
if (!a.is_basic())
|
||||
refine_until_prec(const_cast<numeral&>(a), 1);
|
||||
if (a.is_basic()) {
|
||||
qm().ceil(basic_value(a), v);
|
||||
qm().inc(v);
|
||||
}
|
||||
else {
|
||||
refine_until_prec(const_cast<numeral&>(a), 1);
|
||||
else
|
||||
bqm().ceil(qm(), upper(a.to_algebraic()), v);
|
||||
}
|
||||
|
||||
m_wrapper.set(b, v);
|
||||
}
|
||||
|
||||
|
|
|
@ -2504,30 +2504,139 @@ namespace polynomial {
|
|||
return p;
|
||||
}
|
||||
|
||||
void gcd_simplify(polynomial * p) {
|
||||
if (m_manager.finite()) return;
|
||||
void gcd_simplify(polynomial_ref& p, manager::ineq_type t) {
|
||||
auto& m = m_manager.m();
|
||||
unsigned sz = p->size();
|
||||
if (sz == 0)
|
||||
return;
|
||||
unsigned g = 0;
|
||||
for (unsigned i = 0; i < sz; i++) {
|
||||
for (unsigned i = 0; i < sz; i++) {
|
||||
if (!m.is_int(p->a(i))) {
|
||||
gcd_simplify_slow(p, t);
|
||||
return;
|
||||
}
|
||||
if (t != EQ && is_unit(p->m(i)))
|
||||
continue;
|
||||
int j = m.get_int(p->a(i));
|
||||
if (j == INT_MIN || j == 1 || j == -1)
|
||||
if (j == INT_MIN) {
|
||||
gcd_simplify_slow(p, t);
|
||||
return;
|
||||
}
|
||||
if (j == 1 || j == -1)
|
||||
return;
|
||||
g = u_gcd(abs(j), g);
|
||||
if (g == 1)
|
||||
return;
|
||||
}
|
||||
scoped_mpz r(m), gg(m);
|
||||
scoped_mpz gg(m);
|
||||
m.set(gg, g);
|
||||
for (unsigned i = 0; i < sz; ++i) {
|
||||
m.div_gcd(p->a(i), gg, r);
|
||||
m.set(p->a(i), r);
|
||||
apply_gcd_simplify(gg, p, t);
|
||||
}
|
||||
|
||||
void apply_gcd_simplify(mpz & g, polynomial_ref& p, manager::ineq_type t) {
|
||||
|
||||
auto& m = m_manager.m();
|
||||
|
||||
#if 0
|
||||
m.display(verbose_stream() << "gcd ", g);
|
||||
p->display(verbose_stream() << "\n", m_manager, false);
|
||||
char const* tt = "";
|
||||
switch (t) {
|
||||
case ineq_type::GT: tt = ">"; break;
|
||||
case ineq_type::LT: tt = "<"; break;
|
||||
case ineq_type::EQ: tt = "="; break;
|
||||
}
|
||||
verbose_stream() << " " << tt << " 0\n ->\n";
|
||||
#endif
|
||||
scoped_mpz r(m);
|
||||
unsigned sz = p->size();
|
||||
m_som_buffer.reset();
|
||||
for (unsigned i = 0; i < sz; ++i) {
|
||||
if (t != EQ && is_unit(p->m(i))) {
|
||||
scoped_mpz one(m);
|
||||
m.set(one, 1);
|
||||
if (t == GT) {
|
||||
// p - 2 - 1 >= 0
|
||||
// p div 2 + floor((-2 - 1 ) / 2) >= 0
|
||||
// p div 2 + floor(-3 / 2) >= 0
|
||||
// p div 2 - 2 >= 0
|
||||
// p div 2 - 1 > 0
|
||||
//
|
||||
// p + k > 0
|
||||
// p + k - 1 >= 0
|
||||
// p div g + (k - 1) div g >= 0
|
||||
// p div g + (k - 1) div g + 1 > 0
|
||||
m.sub(p->a(i), one, r);
|
||||
bool is_neg = m.is_neg(r);
|
||||
if (is_neg) {
|
||||
m.neg(r);
|
||||
m.add(r, g, r);
|
||||
m.sub(r, one, r);
|
||||
m.div_gcd(r, g, r);
|
||||
m.neg(r);
|
||||
}
|
||||
else {
|
||||
m.div_gcd(r, g, r);
|
||||
}
|
||||
m.add(r, one, r);
|
||||
}
|
||||
else {
|
||||
// p + k < 0
|
||||
// p + k + 1 <= 0
|
||||
// p div g + (k + 1 + g - 1) div g <= 0
|
||||
// p div g + (k + 1 + g - 1) div g - 1 < 0
|
||||
|
||||
m.add(p->a(i), one, r);
|
||||
bool is_neg = m.is_neg(r);
|
||||
|
||||
if (is_neg) {
|
||||
// p - k <= 0
|
||||
// p <= k
|
||||
// p div g <= k div g
|
||||
// p div g - k div g <= 0
|
||||
// p div g - k div g - 1 < 0
|
||||
m.neg(r);
|
||||
m.div_gcd(r, g, r);
|
||||
m.neg(r);
|
||||
m.sub(r, one, r);
|
||||
}
|
||||
else {
|
||||
m.div_gcd(p->a(i), g, r);
|
||||
m.add(p->a(i), g, r);
|
||||
m.div_gcd(r, g, r);
|
||||
m.sub(r, one, r);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
else {
|
||||
m.div_gcd(p->a(i), g, r);
|
||||
}
|
||||
if (!m.is_zero(r))
|
||||
m_som_buffer.add(r, p->m(i));
|
||||
}
|
||||
p = m_som_buffer.mk();
|
||||
|
||||
// p->display(verbose_stream(), m_manager, false);
|
||||
// verbose_stream() << " " << tt << " 0\n";
|
||||
}
|
||||
|
||||
void gcd_simplify_slow(polynomial_ref& p, manager::ineq_type t) {
|
||||
auto& m = m_manager.m();
|
||||
unsigned sz = p->size();
|
||||
scoped_mpz g(m);
|
||||
m.set(g, 0);
|
||||
for (unsigned i = 0; i < sz; i++) {
|
||||
auto const& a = p->a(i);
|
||||
if (m.is_one(a) || m.is_minus_one(a))
|
||||
return;
|
||||
if (t != EQ && is_unit(p->m(i)))
|
||||
continue;
|
||||
m.gcd(a, g, g);
|
||||
if (m.is_one(g))
|
||||
return;
|
||||
}
|
||||
apply_gcd_simplify(g, p, t);
|
||||
}
|
||||
|
||||
polynomial * mk_zero() {
|
||||
|
@ -6087,9 +6196,11 @@ namespace polynomial {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
if (!m_manager.ge(a1, a2))
|
||||
return false;
|
||||
++i, ++j;
|
||||
if (m_manager.eq(a1, a2) || (m1->is_square() && m_manager.ge(a1, a2))) {
|
||||
++i, ++j;
|
||||
continue;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return i == sz1 && j == sz2;
|
||||
}
|
||||
|
@ -6971,8 +7082,8 @@ namespace polynomial {
|
|||
return m_imp->hash(p);
|
||||
}
|
||||
|
||||
void manager::gcd_simplify(polynomial * p) {
|
||||
m_imp->gcd_simplify(p);
|
||||
void manager::gcd_simplify(polynomial_ref& p, ineq_type t) {
|
||||
m_imp->gcd_simplify(p, t);
|
||||
}
|
||||
|
||||
polynomial * manager::coeff(polynomial const * p, var x, unsigned k) {
|
||||
|
|
|
@ -285,7 +285,8 @@ namespace polynomial {
|
|||
/**
|
||||
\brief Normalize coefficients by dividing by their gcd
|
||||
*/
|
||||
void gcd_simplify(polynomial* p);
|
||||
enum ineq_type { EQ, LT, GT };
|
||||
void gcd_simplify(polynomial_ref& p, ineq_type t);
|
||||
|
||||
/**
|
||||
\brief Return true if \c m is the unit monomial.
|
||||
|
|
|
@ -117,20 +117,14 @@ namespace polynomial {
|
|||
}
|
||||
|
||||
void reset_psc_chain_cache() {
|
||||
psc_chain_cache::iterator it = m_psc_chain_cache.begin();
|
||||
psc_chain_cache::iterator end = m_psc_chain_cache.end();
|
||||
for (; it != end; ++it) {
|
||||
del_psc_chain_entry(*it);
|
||||
}
|
||||
for (auto & k : m_psc_chain_cache)
|
||||
del_psc_chain_entry(k);
|
||||
m_psc_chain_cache.reset();
|
||||
}
|
||||
|
||||
void reset_factor_cache() {
|
||||
factor_cache::iterator it = m_factor_cache.begin();
|
||||
factor_cache::iterator end = m_factor_cache.end();
|
||||
for (; it != end; ++it) {
|
||||
del_factor_entry(*it);
|
||||
}
|
||||
for (auto & e : m_factor_cache)
|
||||
del_factor_entry(e);
|
||||
m_factor_cache.reset();
|
||||
}
|
||||
|
||||
|
@ -139,7 +133,6 @@ namespace polynomial {
|
|||
polynomial * mk_unique(polynomial * p) {
|
||||
if (m_in_cache.get(pid(p), false))
|
||||
return p;
|
||||
// m.gcd_simplify(p);
|
||||
polynomial * p_prime = m_poly_table.insert_if_not_there(p);
|
||||
if (p == p_prime) {
|
||||
m_cached_polys.push_back(p_prime);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue