void operator()(app * n) { if (!compatible_sort(n)) throw found(); family_id fid = n->get_family_id(); if (fid == m.get_basic_family_id()) return; if (fid == u.get_family_id()) { switch (n->get_decl_kind()) { case OP_LE: case OP_GE: case OP_LT: case OP_GT: case OP_ADD: case OP_NUM: return; case OP_MUL: if (n->get_num_args() != 2) throw found(); if (!u.is_numeral(n->get_arg(0))) throw found(); return; case OP_TO_REAL: if (!m_real) throw found(); break; default: throw found(); } return; } if (is_uninterp_const(n)) return; throw found(); }
bool compatible_sort(app * n) const { if (m.is_bool(n)) return true; if (m_int && u.is_int(n)) return true; if (m_real && u.is_real(n)) return true; return false; }
void operator()(var * x) { if (!m_quant) throw_found(); sort * s = x->get_sort(); if (m_int && u.is_int(s)) return; if (m_real && u.is_real(s)) return; throw_found(); }
bool compatible_sort(app * n) const { if (m.is_bool(n)) return true; if (m_int && m_arith_util.is_int(n)) return true; if (m_real && m_arith_util.is_real(n)) return true; if (m_array_util.is_array(n)) return true; return false; }
subpaving::var process_mul(app * t, unsigned depth, mpz & n, mpz & d) { unsigned num_args = t->get_num_args(); if (num_args <= 1) found_non_simplified(); rational k; expr * m; if (m_autil.is_numeral(t->get_arg(0), k)) { if (num_args != 2) found_non_simplified(); qm().set(n, k.to_mpq().numerator()); qm().set(d, k.to_mpq().denominator()); m = t->get_arg(1); } else { qm().set(n, 1); qm().set(d, 1); m = t; } expr * const * margs; unsigned sz; if (m_autil.is_mul(m)) { margs = to_app(m)->get_args(); sz = to_app(m)->get_num_args(); } else { margs = &m; sz = 1; } scoped_mpz n_arg(qm()); scoped_mpz d_arg(qm()); sbuffer<subpaving::power> pws; for (unsigned i = 0; i < sz; i++) { expr * arg = margs[i]; unsigned k; as_power(arg, arg, k); subpaving::var x_arg = process(arg, depth+1, n_arg, d_arg); qm().power(n_arg, k, n_arg); qm().power(d_arg, k, d_arg); qm().mul(n, n_arg, n); qm().mul(d, d_arg, d); if (x_arg != subpaving::null_var) pws.push_back(subpaving::power(x_arg, k)); } subpaving::var x; if (pws.empty()) x = subpaving::null_var; else if (pws.size() == 1 && pws[0].degree() == 1) x = pws[0].get_var(); else x = s().mk_monomial(pws.size(), pws.c_ptr()); cache_result(t, x, n, d); return x; }
subpaving::var mk_var_for(expr * t) { SASSERT(!m_autil.is_numeral(t)); subpaving::var x = m_expr2var->to_var(t); if (x == subpaving::null_var) { bool is_int = m_autil.is_int(t); x = s().mk_var(is_int); m_expr2var->insert(t, x); if (x >= m_var2expr.size()) m_var2expr.resize(x+1, 0); m_var2expr.set(x, t); } return x; }
void operator()(app * n) { if (!compatible_sort(n)) throw_found(); family_id fid = n->get_family_id(); if (fid == m.get_basic_family_id()) return; if (fid == u.get_family_id()) { switch (n->get_decl_kind()) { case OP_LE: case OP_GE: case OP_LT: case OP_GT: case OP_ADD: case OP_UMINUS: case OP_SUB: case OP_ABS: case OP_NUM: return; case OP_MUL: if (m_linear) { if (n->get_num_args() != 2) throw_found(); if (!u.is_numeral(n->get_arg(0))) throw_found(); } return; case OP_IDIV: case OP_DIV: case OP_REM: case OP_MOD: if (m_linear && !u.is_numeral(n->get_arg(1))) throw_found(); return; case OP_IS_INT: if (m_real) throw_found(); return; case OP_TO_INT: case OP_TO_REAL: return; case OP_POWER: if (m_linear) throw_found(); return; case OP_IRRATIONAL_ALGEBRAIC_NUM: if (m_linear || !m_real) throw_found(); return; default: throw_found(); } return; } if (is_uninterp_const(n)) return; throw_found(); }
// Put t as a^k. void as_power(expr * t, expr * & a, unsigned & k) { if (!m_autil.is_power(t)) { a = t; k = 1; return; } rational _k; if (!m_autil.is_numeral(to_app(t)->get_arg(1), _k) || !_k.is_int() || !_k.is_unsigned()) { a = t; k = 1; return; } a = to_app(t)->get_arg(0); k = _k.get_unsigned(); }
subpaving::var process_num(app * t, unsigned depth, mpz & n, mpz & d) { rational k; VERIFY(m_autil.is_numeral(t, k)); qm().set(n, k.to_mpq().numerator()); qm().set(d, k.to_mpq().denominator()); return subpaving::null_var; }
void operator()(app * n) { sort * s = get_sort(n); if (!m.is_bool(s) && !fu.is_float(s) && !fu.is_rm(s) && !bu.is_bv_sort(s) && !au.is_real(s)) throw found(); family_id fid = n->get_family_id(); if (fid == m.get_basic_family_id()) return; if (fid == fu.get_family_id() || fid == bu.get_family_id()) return; if (is_uninterp_const(n)) return; if (au.is_real(s) && au.is_numeral(n)) return; throw found(); }
u2i_cfg(ast_manager & m, sort * u): m_autil(m), m_asts(m), m_usort(u) { m_asts.push_back(u); m_int_sort = m_autil.mk_int(); m_asts.push_back(m_int_sort); }
void operator()(app* a) { if (is_arith_op(a) || a->get_family_id() == m.get_basic_family_id()) { return; } if (m_arith.is_int_real(a)) { m_avars.push_back(a); if (!m_seen.contains(a)) { m_proxies.push_back(a); m_seen.insert(a); } } for (expr* arg : *a) { if (is_app(arg) && !m_seen.contains(arg) && m_arith.is_int_real(arg)) { m_proxies.push_back(to_app(arg)); m_seen.insert(arg); } } }
void operator()(app * t) { if (is_uninterp_const(t) && (m_util.is_int(t) || m_util.is_real(t))) { if (!m_bm.has_lower(t)) { m_set.assert_expr(m_util.mk_le(t, m_util.mk_numeral(m_upper, m_util.is_int(t)))); m_num_bounds++; } if (!m_bm.has_upper(t)) { m_set.assert_expr(m_util.mk_ge(t, m_util.mk_numeral(m_lower, m_util.is_int(t)))); m_num_bounds++; } } }
void operator()(app * n) { rational val; if (m_util.is_numeral(n, val)) { unsigned bw = val.bitsize(); if (bw > m_max_bw) m_max_bw = bw; m_acc_bw += bw; m_counter++; } }
void operator()(app * n) { family_id fid = n->get_family_id(); if (fid == m.get_basic_family_id()) return; if (fid == u.get_family_id()) { switch (n->get_decl_kind()) { case OP_LE: case OP_GE: case OP_LT: case OP_GT: case OP_ADD: case OP_UMINUS: case OP_SUB: case OP_ABS: case OP_NUM: case OP_IRRATIONAL_ALGEBRAIC_NUM: return; case OP_MUL: if (n->get_num_args() == 2 && u.is_real(n->get_arg(0)) && !u.is_numeral(n->get_arg(0)) && !u.is_numeral(n->get_arg(1))) { m_has_nonlinear = true; } return; case OP_IDIV: case OP_DIV: case OP_REM: case OP_MOD: if (!u.is_numeral(n->get_arg(1))) throw_found(); return; case OP_POWER: if (!u.is_numeral(n->get_arg(1))) throw_found(); m_has_nonlinear = true; return; case OP_IS_INT: case OP_TO_INT: case OP_TO_REAL: throw_found(); return; default: throw_found(); } } }
subpaving::var process_arith_app(app * t, unsigned depth, mpz & n, mpz & d) { SASSERT(m_autil.is_arith_expr(t)); switch (t->get_decl_kind()) { case OP_NUM: return process_num(t, depth, n, d); case OP_ADD: return process_add(t, depth, n, d); case OP_MUL: return process_mul(t, depth, n, d); case OP_POWER: return process_power(t, depth, n, d); case OP_TO_REAL: return process(t->get_arg(0), depth+1, n, d); case OP_SUB: case OP_UMINUS: found_non_simplified(); break; case OP_TO_INT: case OP_DIV: case OP_IDIV: case OP_MOD: case OP_REM: case OP_IRRATIONAL_ALGEBRAIC_NUM: throw default_exception("you must apply arithmetic purifier before internalizing expressions into the subpaving module."); case OP_SIN: case OP_COS: case OP_TAN: case OP_ASIN: case OP_ACOS: case OP_ATAN: case OP_SINH: case OP_COSH: case OP_TANH: case OP_ASINH: case OP_ACOSH: case OP_ATANH: // TODO throw default_exception("transcendental and hyperbolic functions are not supported yet."); default: UNREACHABLE(); } return subpaving::null_var; }
subpaving::var process_power(app * t, unsigned depth, mpz & n, mpz & d) { rational k; SASSERT(t->get_num_args() == 2); if (!m_autil.is_numeral(t->get_arg(1), k) || !k.is_int() || !k.is_unsigned()) { qm().set(n, 1); qm().set(d, 1); return mk_var_for(t); } unsigned _k = k.get_unsigned(); subpaving::var x = process(t->get_arg(0), depth+1, n, d); if (x != subpaving::null_var) { subpaving::power p(x, _k); x = s().mk_monomial(1, &p); } qm().power(n, _k, n); qm().power(d, _k, d); cache_result(t, x, n, d); return x; }
subpaving::var process(expr * t, unsigned depth, mpz & n, mpz & d) { SASSERT(is_int_real(t)); checkpoint(); if (is_cached(t)) { unsigned idx = m_cache.find(t); qm().set(n, m_cached_numerators[idx]); qm().set(d, m_cached_denominators[idx]); return m_cached_vars[idx]; } SASSERT(!is_quantifier(t)); if (::is_var(t) || !m_autil.is_arith_expr(t)) { qm().set(n, 1); qm().set(d, 1); return mk_var_for(t); } return process_arith_app(to_app(t), depth, n, d); }
void operator()(app * n) { if (m_util.is_le(n) || m_util.is_lt(n) || m_util.is_gt(n) || m_util.is_ge(n)) process(n); if (m.is_eq(n) && m_util.is_int_real(n->get_arg(0))) process(n); }
bool is_arith_op(app* a) { return a->get_family_id() == m_arith.get_family_id(); }
bool is_int_real(expr * t) { return m_autil.is_int_real(t); }
void operator()(app * t) { if (is_uninterp_const(t) && (m_util.is_int(t) || m_util.is_real(t)) && (!m_bm.has_lower(t) || !m_bm.has_upper(t))) throw found(); }