3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-08 10:25:18 +00:00
This commit is contained in:
Nikolaj Bjorner 2020-11-08 17:18:05 -08:00
parent 89ffb45c4f
commit e2c1436cc8
2 changed files with 51 additions and 42 deletions

View file

@ -196,8 +196,9 @@ void arith_decl_plugin::set_manager(ast_manager * m, family_id id) {
m_is_int_decl = m->mk_func_decl(symbol("is_int"), r, m->mk_bool_sort(), func_decl_info(id, OP_IS_INT));
m->inc_ref(m_is_int_decl);
m_i_power_decl = m->mk_func_decl(symbol("^"), i, i, r, func_decl_info(id, OP_POWER));
m->inc_ref(m_i_power_decl);
MK_OP(m_r_power_decl, "^", OP_POWER, r);
MK_OP(m_i_power_decl, "^", OP_POWER, i);
MK_UNARY(m_i_abs_decl, "abs", OP_ABS, i);
MK_UNARY(m_r_abs_decl, "abs", OP_ABS, r);

View file

@ -254,8 +254,14 @@ bool arith_rewriter::is_non_negative(expr* e) {
unsigned pu;
return m_util.is_power(e, n, p) && m_util.is_unsigned(p, pu) && (pu % 2 == 0);
};
auto is_power_of_positive = [&](expr* e) {
expr* n = nullptr, * p = nullptr;
return m_util.is_power(e, n, p) && m_util.is_numeral(n, r) && r.is_pos();
};
if (is_even_power(e))
return true;
if (is_power_of_positive(e))
return true;
if (seq().str.is_length(e))
return true;
if (!m_util.is_mul(e))
@ -267,6 +273,8 @@ bool arith_rewriter::is_non_negative(expr* e) {
for (expr* arg : args) {
if (is_even_power(arg))
continue;
if (is_power_of_positive(arg))
continue;
if (seq().str.is_length(e))
continue;
if (m_util.is_numeral(arg, r)) {
@ -1242,38 +1250,47 @@ br_status arith_rewriter::mk_power_core(expr * arg1, expr * arg2, expr_ref & res
numeral x, y;
bool is_num_x = m_util.is_numeral(arg1, x);
bool is_num_y = m_util.is_numeral(arg2, y);
bool is_int_sort = m_util.is_int(arg1);
auto ensure_real = [&](expr* e) { return m_util.is_int(e) ? m_util.mk_to_real(e) : e; };
TRACE("arith", tout << mk_pp(arg1, m()) << " " << mk_pp(arg2, m()) << "\n";);
if ((is_num_x && x.is_one()) ||
(is_num_y && y.is_one())) {
result = arg1;
if (is_num_x && x.is_one()) {
result = m_util.mk_numeral(rational(0), false);
return BR_DONE;
}
if (is_num_y && y.is_one()) {
result = ensure_real(arg1);
return BR_REWRITE1;
}
if (is_num_x && is_num_y) {
if (x.is_zero() && y.is_zero())
return BR_FAILED;
if (y.is_zero()) {
result = m_util.mk_numeral(rational(1), m().get_sort(arg1));
result = m_util.mk_numeral(rational(1), false);
return BR_DONE;
}
if (x.is_zero()) {
result = arg1;
result = m_util.mk_numeral(x, false);
return BR_DONE;
}
if (y.is_unsigned() && y.get_unsigned() <= m_max_degree) {
x = power(x, y.get_unsigned());
result = m_util.mk_numeral(x, m().get_sort(arg1));
result = m_util.mk_numeral(x, false);
return BR_DONE;
}
if (!is_int_sort && (-y).is_unsigned() && (-y).get_unsigned() <= m_max_degree) {
if ((-y).is_unsigned() && (-y).get_unsigned() <= m_max_degree) {
x = power(rational(1)/x, (-y).get_unsigned());
result = m_util.mk_numeral(x, m().get_sort(arg1));
result = m_util.mk_numeral(x, false);
return BR_DONE;
}
if (y.is_minus_one()) {
result = m_util.mk_numeral(rational(1) / x, false);
return BR_DONE;
}
}
@ -1283,26 +1300,31 @@ br_status arith_rewriter::mk_power_core(expr * arg1, expr * arg2, expr_ref & res
// (^ (^ t y2) y) --> (^ t (* y2 y)) If y2 > 0 && y != 0 && y and y2 are integers
rational y2;
if (m_util.is_numeral(arg11, y2) && y2.is_int() && y2.is_pos()) {
result = m_util.mk_power(arg10, m_util.mk_numeral(y*y2, is_int_sort));
return BR_REWRITE1;
result = m_util.mk_power(ensure_real(arg10), m_util.mk_numeral(y*y2, false));
return BR_REWRITE2;
}
}
if (!is_int_sort && is_num_y && y.is_neg()) {
if (is_num_y && y.is_minus_one()) {
result = m_util.mk_div(m_util.mk_real(1), ensure_real(arg1));
return BR_REWRITE2;
}
if (is_num_y && y.is_neg()) {
// (^ t -k) --> (^ (/ 1 t) k)
result = m_util.mk_power(m_util.mk_div(m_util.mk_numeral(rational(1), false), arg1),
m_util.mk_numeral(-y, false));
result = m().mk_ite(m().mk_eq(arg1, m_util.mk_real(0)),
result = m().mk_ite(m().mk_eq(arg1, m_util.mk_numeral(rational(0), m_util.is_int(arg1))),
m_util.mk_real(0),
result);
return BR_REWRITE3;
}
if (!is_int_sort && is_num_y && !y.is_int() && !numerator(y).is_one()) {
if (is_num_y && !y.is_int() && !numerator(y).is_one()) {
// (^ t (/ p q)) --> (^ (^ t (/ 1 q)) p)
result = m_util.mk_power(m_util.mk_power(arg1, m_util.mk_numeral(rational(1)/denominator(y), false)),
result = m_util.mk_power(m_util.mk_power(ensure_real(arg1), m_util.mk_numeral(rational(1)/denominator(y), false)),
m_util.mk_numeral(numerator(y), false));
return BR_REWRITE2;
return BR_REWRITE3;
}
if ((m_expand_power || (m_som && is_app(arg1) && to_app(arg1)->get_family_id() == get_fid())) &&
@ -1312,8 +1334,8 @@ br_status arith_rewriter::mk_power_core(expr * arg1, expr * arg2, expr_ref & res
for (unsigned i = 0; i < k; i++) {
args.push_back(arg1);
}
result = m_util.mk_mul(args.size(), args.c_ptr());
return BR_REWRITE1;
result = ensure_real(m_util.mk_mul(args.size(), args.c_ptr()));
return BR_REWRITE2;
}
if (!is_num_y)
@ -1338,9 +1360,6 @@ br_status arith_rewriter::mk_power_core(expr * arg1, expr * arg2, expr_ref & res
SASSERT(num_y.is_pos());
SASSERT(den_y.is_pos());
if (is_neg_y && is_int_sort)
return BR_FAILED;
if (!num_y.is_unsigned() || !den_y.is_unsigned())
return BR_FAILED;
@ -1359,7 +1378,7 @@ br_status arith_rewriter::mk_power_core(expr * arg1, expr * arg2, expr_ref & res
if (xk.root(u_den_y, r)) {
if (is_neg_y)
r = rational(1)/r;
result = m_util.mk_numeral(r, m().get_sort(arg1));
result = m_util.mk_numeral(r, false);
return BR_DONE;
}
if (m_anum_simp) {
@ -1452,10 +1471,8 @@ br_status arith_rewriter::mk_to_real_core(expr * arg, expr_ref & result) {
if (m_push_to_real) {
if (m_util.is_add(arg) || m_util.is_mul(arg)) {
ptr_buffer<expr> new_args;
unsigned num = to_app(arg)->get_num_args();
for (unsigned i = 0; i < num; i++) {
new_args.push_back(m_util.mk_to_real(to_app(arg)->get_arg(i)));
}
for (expr* e : *to_app(arg))
new_args.push_back(m_util.mk_to_real(e));
if (m_util.is_add(arg))
result = m().mk_app(get_fid(), OP_ADD, new_args.size(), new_args.c_ptr());
else
@ -1505,14 +1522,11 @@ bool arith_rewriter::is_pi_multiple(expr * t, rational & k) {
// Store c into k, and c*Pi into m.
bool arith_rewriter::is_pi_offset(expr * t, rational & k, expr * & m) {
if (m_util.is_add(t)) {
unsigned num = to_app(t)->get_num_args();
for (unsigned i = 0; i < num; i++) {
expr * arg = to_app(t)->get_arg(i);
for (expr* arg : *to_app(t))
if (is_pi_multiple(arg, k)) {
m = arg;
return true;
}
}
}
}
return false;
}
@ -1534,14 +1548,11 @@ bool arith_rewriter::is_2_pi_integer(expr * t) {
// Store 2*pi*to_real(s) into m.
bool arith_rewriter::is_2_pi_integer_offset(expr * t, expr * & m) {
if (m_util.is_add(t)) {
unsigned num = to_app(t)->get_num_args();
for (unsigned i = 0; i < num; i++) {
expr * arg = to_app(t)->get_arg(i);
for (expr* arg : *to_app(t))
if (is_2_pi_integer(arg)) {
m = arg;
return true;
}
}
}
}
return false;
}
@ -1574,14 +1585,11 @@ bool arith_rewriter::is_pi_integer(expr * t) {
// Store 2*pi*to_real(s) into m.
bool arith_rewriter::is_pi_integer_offset(expr * t, expr * & m) {
if (m_util.is_add(t)) {
unsigned num = to_app(t)->get_num_args();
for (unsigned i = 0; i < num; i++) {
expr * arg = to_app(t)->get_arg(i);
for (expr* arg : *to_app(t))
if (is_pi_integer(arg)) {
m = arg;
return true;
}
}
}
}
return false;
}