示例#1
0
文件: qe_mbp.cpp 项目: ttsvetanov/z3
 bool reduce_eq(expr_mark& is_var, expr* l, expr* r, expr_ref& v, expr_ref& t) {
     if (is_var.is_marked(r)) {
         std::swap(l, r);
     }
     if (is_var.is_marked(l)) {
         contains_app cont(m, to_app(l));
         if (!cont(r)) {
             v = to_app(l);
             t = r;
             return true;
         }
     }
     return false;
 }
bool arith_solver_plugin::solve(expr * lhs, expr * rhs, expr_mark const & forbidden, app_ref & var, expr_ref & subst) {
    rational k;
    if (!m_simplifier.is_numeral(rhs, k))
        return false;
    bool _is_int = m_simplifier.is_int(lhs);
    ptr_buffer<expr> monomials;
    ptr_buffer<expr> todo;
    bool already_found = false;
    rational c;
    todo.push_back(lhs);
    while (!todo.empty()) {
        expr * curr = todo.back();
        todo.pop_back();
        rational coeff;
        if (m_simplifier.is_add(curr)) {
            SASSERT(to_app(curr)->get_num_args() == 2);
            todo.push_back(to_app(curr)->get_arg(1));
            todo.push_back(to_app(curr)->get_arg(0));
        }
        else {
            if (!already_found) {
                if (m_simplifier.is_mul(curr) && 
                    m_simplifier.is_numeral(to_app(curr)->get_arg(0), coeff) && !coeff.is_zero() && (!_is_int || coeff.is_minus_one()) && 
                    is_uninterp_const(to_app(curr)->get_arg(1)) &&
                    !forbidden.is_marked(to_app(curr)->get_arg(1))) {
                    c             = coeff;
                    var           = to_app(to_app(curr)->get_arg(1));
                    already_found = true;
                }
                else if (is_uninterp_const(curr) && !forbidden.is_marked(curr)) {
                    c             = rational::one();
                    var           = to_app(curr);
                    already_found = true;
                }
                else {
                    monomials.push_back(curr);
                }
            }
            else {
                monomials.push_back(curr);
            }
        }
    }
    if (!already_found)
        return false;
    SASSERT(!c.is_zero());
    k /= c;
    expr_ref_vector new_monomials(m_manager);
    if (!k.is_zero())
        new_monomials.push_back(m_simplifier.mk_numeral(k, _is_int));
    c.neg();
    expr_ref inv_c(m_manager);
    if (!c.is_one()) {
        rational inv(1);
        inv /= c;
        inv_c = m_simplifier.mk_numeral(inv, _is_int);
    }
    // divide monomials by c
    unsigned sz = monomials.size();
    for (unsigned i = 0; i < sz; i++) {
        expr * m       = monomials[i];
        expr_ref new_m(m_manager); 
        if (!c.is_one())
            m_simplifier.mk_mul(inv_c, m, new_m);
        else
            new_m = m;
        new_monomials.push_back(new_m);
    }
    if (new_monomials.empty()) 
        subst = m_simplifier.mk_numeral(rational(0), _is_int);
    else
        m_simplifier.mk_add(new_monomials.size(), new_monomials.c_ptr(), subst);
    TRACE("arith_solver", tout << "solving:\n" << mk_pp(lhs, m_manager) << "\n" << mk_pp(rhs, m_manager) 
          << "\nresult:\n" << mk_pp(var, m_manager) << "\n" << mk_pp(subst, m_manager) << "\n";);
示例#3
0
    virtual void operator()(
        goal_ref const & g, 
        goal_ref_buffer & result, 
        model_converter_ref & mc, 
        proof_converter_ref & pc,
        expr_dependency_ref & core) {
        SASSERT(g->is_well_sorted());
        mc = 0; pc = 0; core = 0;
        m_trail.reset();
        m_fd.reset();
        m_max.reset();
        m_nonfd.reset();
        m_bounds.reset();
        ref<bvmc> mc1 = alloc(bvmc);

        tactic_report report("eq2bv", *g);

        m_bounds(*g);

        for (unsigned i = 0; i < g->size(); i++) {            
            collect_fd(g->form(i));
        }
        cleanup_fd(mc1);
        
        if (m_max.empty()) {
            result.push_back(g.get());
            return;
        }

        for (unsigned i = 0; i < g->size(); i++) {            
            expr_ref   new_curr(m);
            proof_ref  new_pr(m);  
            if (is_bound(g->form(i))) {
                g->update(i, m.mk_true(), 0, 0);
                continue;
            }
            m_rw(g->form(i), new_curr, new_pr);
            if (m.proofs_enabled() && !new_pr) {
                new_pr = m.mk_rewrite(g->form(i), new_curr);
                new_pr = m.mk_modus_ponens(g->pr(i), new_pr);
            }
            g->update(i, new_curr, new_pr, g->dep(i));
        }
        obj_map<expr, unsigned>::iterator it = m_max.begin(), end = m_max.end();
        for (; it != end; ++it) {
            expr* c = it->m_key;
            bool strict;
            rational r;
            if (m_bounds.has_lower(c, r, strict)) {
                SASSERT(!strict);
                expr* d = m_fd.find(c);
                g->assert_expr(bv.mk_ule(bv.mk_numeral(r, m.get_sort(d)), d), m_bounds.lower_dep(c));
            }
            if (m_bounds.has_upper(c, r, strict)) {
                SASSERT(!strict);
                expr* d = m_fd.find(c);
                g->assert_expr(bv.mk_ule(d, bv.mk_numeral(r, m.get_sort(d))), m_bounds.upper_dep(c));
            }
        }        
        g->inc_depth();
        mc = mc1.get();
        result.push_back(g.get());
        TRACE("pb", g->display(tout););