Beispiel #1
0
tactic * mk_qflra_tactic(ast_manager & m, params_ref const & p) {
    params_ref pivot_p;
    pivot_p.set_bool("arith.greatest_error_pivot", true);

    params_ref main_p = p;
    main_p.set_bool("elim_and", true);
    main_p.set_bool("som", true);
    main_p.set_bool("blast_distinct", true);
    
    params_ref ctx_simp_p;
    ctx_simp_p.set_uint("max_depth", 30);
    ctx_simp_p.set_uint("max_steps", 5000000);
    
    params_ref lhs_p;
    lhs_p.set_bool("arith_lhs", true);
    lhs_p.set_bool("eq2ineq", true);
    
    params_ref elim_to_real_p;
    elim_to_real_p.set_bool("elim_to_real", true);
    

#if 0
    tactic * mip =
        and_then(fail_if(mk_produce_proofs_probe()),
                 fail_if(mk_produce_unsat_cores_probe()),
                 using_params(and_then(and_then(mk_simplify_tactic(m),
                                                mk_recover_01_tactic(m),
                                                using_params(mk_simplify_tactic(m), elim_to_real_p),
                                                mk_propagate_values_tactic(m)),
                                       using_params(mk_ctx_simplify_tactic(m), ctx_simp_p),
                                       mk_elim_uncnstr_tactic(m),
                                       mk_solve_eqs_tactic(m),
                                       using_params(mk_simplify_tactic(m), lhs_p),
                                       using_params(mk_simplify_tactic(m), elim_to_real_p)
                                       ),
                              main_p),
                 fail_if(mk_not(mk_is_mip_probe())),
                 try_for(mk_mip_tactic(m), 30000),
                 mk_fail_if_undecided_tactic());
#endif

    //    return using_params(or_else(mip,
    //                            using_params(mk_smt_tactic(m), pivot_p)),
    //                    p);

#if 0

    params_ref simplex_0, simplex_1, simplex_2;
    simplex_0.set_uint("lp.simplex_strategy", 0);    
    simplex_1.set_uint("lp.simplex_strategy", 1);    
    simplex_2.set_uint("lp.simplex_strategy", 2);
    
    return par(using_params(mk_smt_tactic(), simplex_0), 
               using_params(mk_smt_tactic(), simplex_1), 
               using_params(mk_smt_tactic(), simplex_2));
#else
    return using_params(using_params(mk_smt_tactic(m), pivot_p), p);
#endif

}
static tactic * mk_quant_preprocessor(ast_manager & m, bool disable_gaussian = false) {
    params_ref pull_ite_p;
    pull_ite_p.set_bool(":pull-cheap-ite", true);
    pull_ite_p.set_bool(":local-ctx", true);
    pull_ite_p.set_uint(":local-ctx-limit", 10000000);
    
    params_ref ctx_simp_p;
    ctx_simp_p.set_uint(":max-depth", 30);
    ctx_simp_p.set_uint(":max-steps", 5000000);

    tactic * solve_eqs;
    if (disable_gaussian)
        solve_eqs = mk_skip_tactic();
    else
        solve_eqs = when(mk_not(mk_has_pattern_probe()), mk_solve_eqs_tactic(m));
 
    // remark: investigate if gaussian elimination is useful when patterns are not provided.
    return and_then(mk_simplify_tactic(m), 
                    mk_propagate_values_tactic(m),
                    using_params(mk_ctx_simplify_tactic(m), ctx_simp_p),
                    using_params(mk_simplify_tactic(m), pull_ite_p),
                    solve_eqs,
                    mk_elim_uncnstr_tactic(m),
                    mk_simplify_tactic(m));    
}
void asserted_formulas::push_assertion(expr * e, proof * pr, vector<justified_expr>& result) {
    if (inconsistent()) {
        return;
    }
    expr* e1 = nullptr;
    if (m.is_false(e)) {
        result.push_back(justified_expr(m, e, pr));
        m_inconsistent = true;
    }
    else if (m.is_true(e)) {
        // skip
    }
    else if (m.is_and(e)) {
        for (unsigned i = 0; i < to_app(e)->get_num_args(); ++i) {
            expr* arg = to_app(e)->get_arg(i);
            proof_ref _pr(m.proofs_enabled() ? m.mk_and_elim(pr, i) : nullptr, m);
            push_assertion(arg, _pr, result);
        }
    }
    else if (m.is_not(e, e1) && m.is_or(e1)) {
        for (unsigned i = 0; i < to_app(e1)->get_num_args(); ++i) {
            expr* arg = to_app(e1)->get_arg(i);
            proof_ref _pr(m.proofs_enabled() ? m.mk_not_or_elim(pr, i) : nullptr, m);
            expr_ref  narg(mk_not(m, arg), m);
            push_assertion(narg, _pr, result);
        }
    }
    else {
        result.push_back(justified_expr(m, e, pr));
    }
}
Beispiel #4
0
 Z3_probe Z3_API Z3_probe_not(Z3_context c, Z3_probe p) {
     Z3_TRY;
     LOG_Z3_probe_not(c, p);
     RESET_ERROR_CODE();
     probe * new_p = mk_not(to_probe_ref(p));
     RETURN_PROBE(new_p);
     Z3_CATCH_RETURN(0);
 }
Beispiel #5
0
 // If restricted is true, we don't use (e <-> true) rewrite
 list<expr_pair> apply(expr const & e, expr const & H, bool restrited) {
     expr c, Hdec, A, arg1, arg2;
     if (is_relation(e)) {
         return mk_singleton(e, H);
     } else if (is_standard(m_env) && is_not(m_env, e, arg1)) {
         expr new_e = mk_iff(arg1, mk_false());
         expr new_H = mk_app(mk_constant(get_iff_false_intro_name()), arg1, H);
         return mk_singleton(new_e, new_H);
     } else if (is_standard(m_env) && is_and(e, arg1, arg2)) {
         // TODO(Leo): we can extend this trick to any type that has only one constructor
         expr H1 = mk_app(mk_constant(get_and_elim_left_name()), arg1, arg2, H);
         expr H2 = mk_app(mk_constant(get_and_elim_right_name()), arg1, arg2, H);
         auto r1 = apply(arg1, H1, restrited);
         auto r2 = apply(arg2, H2, restrited);
         return append(r1, r2);
     } else if (is_pi(e)) {
         expr local = mk_local(m_tc.mk_fresh_name(), binding_name(e), binding_domain(e), binding_info(e));
         expr new_e = instantiate(binding_body(e), local);
         expr new_H = mk_app(H, local);
         auto r = apply(new_e, new_H, restrited);
         unsigned len = length(r);
         if (len == 0) {
             return r;
         } else if (len == 1 && head(r).first == new_e && head(r).second == new_H) {
             return mk_singleton(e, H);
         } else {
             return lift(local, r);
         }
     } else if (is_standard(m_env) && is_ite(e, c, Hdec, A, arg1, arg2) && is_prop(e)) {
         // TODO(Leo): support HoTT mode if users request
         expr not_c = mk_not(m_tc, c);
         expr Hc    = mk_local(m_tc.mk_fresh_name(), c);
         expr Hnc   = mk_local(m_tc.mk_fresh_name(), not_c);
         expr H1    = mk_app({mk_constant(get_implies_of_if_pos_name()),
                              c, arg1, arg2, Hdec, e, Hc});
         expr H2    = mk_app({mk_constant(get_implies_of_if_neg_name()),
                              c, arg1, arg2, Hdec, e, Hnc});
         auto r1    = lift(Hc, apply(arg1, H1, restrited));
         auto r2    = lift(Hnc, apply(arg2, H2, restrited));
         return append(r1, r2);
     } else if (!restrited) {
         constraint_seq cs;
         expr new_e = m_tc.whnf(e, cs);
         if (new_e != e && !cs) {
             if (auto r = apply(new_e, H, true))
                 return r;
         }
         if (is_standard(m_env) && is_prop(e)) {
             expr new_e = mk_iff(e, mk_true());
             expr new_H = mk_app(mk_constant(get_iff_true_intro_name()), arg1, H);
             return mk_singleton(new_e, new_H);
         } else {
             return list<expr_pair>();
         }
     } else {
         return list<expr_pair>();
     }
 }
Beispiel #6
0
// ax + by < k
// <=>
// -ax - by >= -k + 1
// <=>
// a(1-x) + b(1-y) >= -k + a + b + 1
app * pb_util::mk_lt(unsigned num_args, rational const * _coeffs, expr * const * _args, rational const& _k) {
    normalize(num_args, _coeffs, _k);
    expr_ref_vector args(m);
    for (unsigned i = 0; i < num_args; ++i) {
        args.push_back(mk_not(m, _args[i]));
    }
    m_k = floor(m_k);
    m_k.neg();
    m_k += rational::one();
    for (unsigned i = 0; i < num_args; ++i) {
        m_k += m_coeffs[i];
    }
    return mk_ge(num_args, m_coeffs.c_ptr(), args.c_ptr(), m_k);
}
Beispiel #7
0
bool bool_rewriter::simp_nested_eq_ite(expr * t, expr_fast_mark1 & neg_lits, expr_fast_mark2 & pos_lits, expr_ref & result) {
    bool neg = false;
    m_local_ctx_cost += 3;
    if (m().is_not(t)) {
        neg = true;
        t = to_app(t)->get_arg(0);
    }
    if (m().is_iff(t) || m().is_eq(t)) {
        bool modified = false;
        expr * new_lhs = simp_arg(to_app(t)->get_arg(0), neg_lits, pos_lits, modified);
        expr * new_rhs = simp_arg(to_app(t)->get_arg(1), neg_lits, pos_lits, modified);
        if (!modified)
            return false;
        mk_eq(new_lhs, new_rhs, result);
        if (neg)
            mk_not(result, result);
        return true;
    }
    if (m().is_ite(t)) {
        bool modified = false;
        expr * new_c = simp_arg(to_app(t)->get_arg(0), neg_lits, pos_lits, modified);
        expr * new_t = simp_arg(to_app(t)->get_arg(1), neg_lits, pos_lits, modified);
        expr * new_e = simp_arg(to_app(t)->get_arg(2), neg_lits, pos_lits, modified);
        if (!modified)
            return false;
        // It is not safe to invoke mk_ite here, since it can recursively call
        // local_ctx_simp by
        //     - transforming the ITE into an OR
        //     - and invoked mk_or, that will invoke local_ctx_simp
        // mk_ite(new_c, new_t, new_e, result);
        mk_nested_ite(new_c, new_t, new_e, result);
        if (neg)
            mk_not(result, result);
        return true;
    }
    return false;
}
Beispiel #8
0
/**
   \brief Auxiliary method for local_ctx_simp.

   Replace args[i] by true if marked in neg_lits.
   Replace args[i] by false if marked in pos_lits.
*/
bool bool_rewriter::simp_nested_not_or(unsigned num_args, expr * const * args,
                                       expr_fast_mark1 & neg_lits, expr_fast_mark2 & pos_lits, expr_ref & result) {
    ptr_buffer<expr> new_args;
    bool simp = false;
    m_local_ctx_cost += num_args;
    for (unsigned i = 0; i < num_args; i++) {
        expr * arg = args[i];
        if (neg_lits.is_marked(arg)) {
            result = m().mk_false();
            return true;
        }
        if (pos_lits.is_marked(arg)) {
            simp = true;
            continue;
        }
        if (m().is_not(arg)) {
            expr * atom = to_app(arg)->get_arg(0);
            if (neg_lits.is_marked(atom)) {
                simp = true;
                continue;
            }
            if (pos_lits.is_marked(atom)) {
                result = m().mk_false();
                return true;
            }
        }
        new_args.push_back(arg);
    }
    if (simp) {
        switch(new_args.size()) {
        case 0:
            result = m().mk_true();
            return true;
        case 1:
            mk_not(new_args[0], result);
            return true;
        default:
            result = m().mk_not(m().mk_or(new_args.size(), new_args.c_ptr()));
            return true;
        }
    }
    return false;
}
bool basic_simplifier_plugin::reduce(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result) {
    set_reduce_invoked();
    SASSERT(f->get_family_id() == m_manager.get_basic_family_id());
    basic_op_kind k = static_cast<basic_op_kind>(f->get_decl_kind());
    switch (k) {
    case OP_FALSE:
    case OP_TRUE:
        return false;
    case OP_EQ:
        SASSERT(num_args == 2);
        mk_eq(args[0], args[1], result);
        return true;
    case OP_DISTINCT:
        mk_distinct(num_args, args, result);
        return true;
    case OP_ITE:
        SASSERT(num_args == 3);
        mk_ite(args[0], args[1], args[2], result);
        return true;
    case OP_AND:
        mk_and(num_args, args, result);
        return true;
    case OP_OR:
        mk_or(num_args, args, result);
        return true;
    case OP_IMPLIES:
        mk_implies(args[0], args[1], result);
        return true;
    case OP_IFF:
        mk_iff(args[0], args[1], result);
        return true;
    case OP_XOR:
        mk_xor(args[0], args[1], result);
        return true;
    case OP_NOT:
        SASSERT(num_args == 1);
        mk_not(args[0], result);
        return true;
    default:
        UNREACHABLE();
        return false;
    }
}
Beispiel #10
0
/**
   \brief Simpler version of mk_ite, that will not invoke mk_or/mk_and.
   It is used byt local_ctx_simp to prevent a recursive call to local_ctx_simp.
   See comment at simp_nested_eq_ite.
*/
void bool_rewriter::mk_nested_ite(expr * c, expr * t, expr * e, expr_ref & result) {
    if (m().is_true(c)) {
        result = t;
        return;
    }

    if (m().is_false(c)) {
        result = e;
        return;
    }

    if (t == e) {
        result = t;
        return;
    }

    if (m().is_bool(t)) {
        if (m().is_true(t)) {
            if (m().is_false(e)) {
                result = c;
                return;
            }
            result = m().mk_or(c, e);
            return;
        }
        if (m().is_false(t)) {
            if (m().is_true(e)) {
                mk_not(c, result);
                return;
            }
            expr_ref tmp(m());
            mk_not(e, tmp);
            result = m().mk_not(m().mk_or(c, tmp));
            return;
        }
        if (m().is_true(e)) {
            expr_ref tmp(m());
            mk_not(c, tmp);
            result = m().mk_or(tmp, t);
            return;
        }
        if (m().is_false(e) || c == e) {
            expr_ref tmp1(m());
            expr_ref tmp2(m());
            mk_not(c, tmp1);
            mk_not(t, tmp2);
            result = m().mk_not(m().mk_or(tmp1, tmp2));
            return;
        }
        if (c == t) {
            result = m().mk_or(c, e);
            return;
        }
        if (m().is_complement_core(t, e)) { // t = not(e)
            mk_eq(c, t, result);
            return;
        }
        if (m().is_complement_core(e, t)) { // e = not(t)
            mk_eq(c, t, result);
            return;
        }
    }
    result = m().mk_ite(c, t, e);
}
Beispiel #11
0
 void prop_mbi_plugin::block(expr_ref_vector const& lits) {
     m_solver->assert_expr(mk_not(mk_and(lits)));
 }
Beispiel #12
0
probe * mk_quasi_pb_probe() {
    return mk_and(mk_not(mk_is_unbounded_probe()),
                  alloc(quasi_pb_probe));
}
Beispiel #13
0
tactic * mk_qfidl_tactic(ast_manager & m, params_ref const & p) {
    params_ref main_p;
    main_p.set_bool("elim_and", true);
    main_p.set_bool("blast_distinct", true);
    main_p.set_bool("som", true);

    params_ref lhs_p;
    lhs_p.set_bool("arith_lhs", true);

    params_ref lia2pb_p;
    lia2pb_p.set_uint("lia2pb_max_bits", 4);

    params_ref pb2bv_p;
    pb2bv_p.set_uint("pb2bv_all_clauses_limit", 8);

    params_ref pull_ite_p;
    pull_ite_p.set_bool("pull_cheap_ite", true);
    pull_ite_p.set_bool("local_ctx", true);
    pull_ite_p.set_uint("local_ctx_limit", 10000000);

    tactic * preamble_st = and_then(and_then(mk_simplify_tactic(m),
                                             mk_fix_dl_var_tactic(m),
                                             mk_propagate_values_tactic(m),
                                             mk_elim_uncnstr_tactic(m)
                                             ),
                                    and_then(mk_solve_eqs_tactic(m),
                                             using_params(mk_simplify_tactic(m), lhs_p),
                                             mk_propagate_values_tactic(m),
                                             mk_normalize_bounds_tactic(m),
                                             mk_solve_eqs_tactic(m)));

    
    
    params_ref bv_solver_p;
    // The cardinality constraint encoding generates a lot of shared if-then-else's that can be flattened.
    // Several of them are simplified to and/or. If we flat them, we increase a lot the memory consumption.
    bv_solver_p.set_bool("flat", false); 
    bv_solver_p.set_bool("som", false); 
    // dynamic psm seems to work well.
    bv_solver_p.set_sym("gc", symbol("dyn_psm"));

    tactic * bv_solver = using_params(and_then(mk_simplify_tactic(m),
                                               mk_propagate_values_tactic(m),
                                               mk_solve_eqs_tactic(m),
                                               mk_max_bv_sharing_tactic(m),
                                               mk_bit_blaster_tactic(m),
                                               mk_aig_tactic(),
                                               mk_sat_tactic(m)),
                                      bv_solver_p);

    tactic * try2bv = 
        and_then(using_params(mk_lia2pb_tactic(m), lia2pb_p),
                 mk_propagate_ineqs_tactic(m),
                 using_params(mk_pb2bv_tactic(m), pb2bv_p),
                 fail_if(mk_not(mk_is_qfbv_probe())),
                 bv_solver);
    
    params_ref diff_neq_p;
    diff_neq_p.set_uint("diff_neq_max_k", 25);

    tactic * st = cond(mk_and(mk_lt(mk_num_consts_probe(), mk_const_probe(static_cast<double>(BIG_PROBLEM))),
                              mk_and(mk_not(mk_produce_proofs_probe()),
                                     mk_not(mk_produce_unsat_cores_probe()))),
                       using_params(and_then(preamble_st,
                                             or_else(using_params(mk_diff_neq_tactic(m), diff_neq_p),
                                                     try2bv,
                                                     mk_smt_tactic())),
                                    main_p),
                       mk_smt_tactic());
    
    st->updt_params(p);

    return st;
}
Beispiel #14
0
probe * mk_lt(probe * p1, probe * p2) {
    return mk_not(mk_ge(p1, p2));
}
Beispiel #15
0
probe * mk_neq(probe * p1, probe * p2) {
    return mk_not(mk_eq(p1, p2));
}
Beispiel #16
0
probe * mk_implies(probe * p1, probe * p2) {
    return mk_or(mk_not(p1), p2);
}