void arith_simplifier_plugin::div_monomial(expr_ref_vector& monomials, numeral const& g) { numeral n; for (unsigned i = 0; i < monomials.size(); ++i) { expr* e = monomials[i].get(); if (is_numeral(e, n)) { SASSERT((n/g).is_int()); monomials[i] = mk_numeral(n/g); } else if (is_mul(e) && is_numeral(to_app(e)->get_arg(0), n)) { SASSERT((n/g).is_int()); monomials[i] = mk_mul(n/g, to_app(e)->get_arg(1)); } else { UNREACHABLE(); } } }
bool static_features::is_non_linear(expr * e) const { if (!is_arith_expr(e)) return false; if (is_numeral(e)) return true; if (m_autil.is_add(e)) return true; // the non }
/** \brief Traverse args, and copy the non-numeral exprs to result, and accumulate the value of the numerals in k. */ void poly_simplifier_plugin::process_monomial(unsigned num_args, expr * const * args, numeral & k, ptr_buffer<expr> & result) { rational v; for (unsigned i = 0; i < num_args; i++) { expr * arg = args[i]; if (is_numeral(arg, v)) k *= v; else result.push_back(arg); } }
void arith_simplifier_plugin::get_monomial_gcd(expr_ref_vector& monomials, numeral& g) { g = numeral::zero(); numeral n; for (unsigned i = 0; !g.is_one() && i < monomials.size(); ++i) { expr* e = monomials[i].get(); if (is_numeral(e, n)) { g = gcd(abs(n), g); } else if (is_mul(e) && is_numeral(to_app(e)->get_arg(0), n)) { g = gcd(abs(n), g); } else { g = numeral::one(); return; } } if (g.is_zero()) { g = numeral::one(); } }
expr * poly_simplifier_plugin::mk_mul(unsigned num_args, expr * const * args) { SASSERT(num_args > 0); #ifdef Z3DEBUG // check for incorrect use of mk_mul set_curr_sort(args[0]); SASSERT(!is_zero(args[0])); numeral k; for (unsigned i = 0; i < num_args; i++) { SASSERT(!is_numeral(args[i], k) || !k.is_one()); SASSERT(i == 0 || !is_numeral(args[i])); } #endif if (num_args == 1) return args[0]; else if (num_args == 2) return m_manager.mk_app(m_fid, m_MUL, args[0], args[1]); else if (is_numeral(args[0])) return m_manager.mk_app(m_fid, m_MUL, args[0], m_manager.mk_app(m_fid, m_MUL, num_args - 1, args+1)); else return m_manager.mk_app(m_fid, m_MUL, num_args, args); }
// check if n has at most one argument that is not numeral. void check_mul(app * n) { if (m_nonlinear) return; // nothing to check unsigned num_args = n->get_num_args(); bool found_non_numeral = false; for (unsigned i = 0; i < num_args; i++) { if (!is_numeral(n->get_arg(i))) { if (found_non_numeral) fail("logic does not support nonlinear arithmetic"); else found_non_numeral = true; } } }
/** \brief Return true if m is a wellformed monomial. */ bool poly_simplifier_plugin::wf_monomial(expr * m) const { SASSERT(!is_add(m)); if (is_mul(m)) { app * curr = to_app(m); expr * pp = 0; if (is_numeral(curr->get_arg(0))) pp = curr->get_arg(1); else pp = curr; if (is_mul(pp)) { for (unsigned i = 0; i < to_app(pp)->get_num_args(); i++) { expr * arg = to_app(pp)->get_arg(i); CTRACE("wf_monomial_bug", is_mul(arg), tout << "m: " << mk_ismt2_pp(m, m_manager) << "\n"; tout << "pp: " << mk_ismt2_pp(pp, m_manager) << "\n"; tout << "arg: " << mk_ismt2_pp(arg, m_manager) << "\n"; tout << "i: " << i << "\n"; ); SASSERT(!is_mul(arg)); SASSERT(!is_numeral(arg)); } } }
expr * poly_simplifier_plugin::mk_mul(numeral const & c, expr * body) { numeral c_prime, d; c_prime = norm(c); if (c_prime.is_zero()) return 0; if (body == 0) return mk_numeral(c_prime); if (c_prime.is_one()) return body; if (is_numeral(body, d)) { c_prime = norm(c_prime*d); if (c_prime.is_zero()) return 0; return mk_numeral(c_prime); } set_curr_sort(body); expr * args[2] = { mk_numeral(c_prime), body }; return mk_mul(2, args); }
bool static_features::is_diff_atom(expr const * e) const { if (!is_bool(e)) return false; if (!m_manager.is_eq(e) && !is_arith_expr(e)) return false; SASSERT(to_app(e)->get_num_args() == 2); expr * lhs = to_app(e)->get_arg(0); SASSERT(is_numeral(to_app(e)->get_arg(1))); // lhs can be 'x' or '(+ x (* -1 y))' if (!is_arith_expr(lhs)) return true; SASSERT(is_app(lhs)); // lhs must be (+ x (* -1 y)) if (to_app(lhs)->get_decl_kind() != OP_ADD || to_app(lhs)->get_num_args() != 2) return false; // x if (is_arith_expr(to_app(lhs)->get_arg(0))) return false; expr * arg2 = to_app(lhs)->get_arg(1); // arg2: (* -1 y) return m_autil.is_mul(arg2) && to_app(arg2)->get_num_args() == 2 && is_minus_one(to_app(arg2)->get_arg(0)) && !is_arith_expr(to_app(arg2)->get_arg(1)); }
// check if the divisor is a numeral void check_div(app * n) { SASSERT(n->get_num_args() == 2); if (!m_nonlinear && !is_numeral(n->get_arg(1))) fail("logic does not support nonlinear arithmetic"); }
rational const & sexpr::get_numeral() const { SASSERT(is_numeral() || is_bv_numeral()); return static_cast<sexpr_numeral const *>(this)->m_val; }
bool fpa_decl_plugin::is_numeral(expr * n) { scoped_mpf v(m_fm); return is_numeral(n, v); }