mirror of
https://github.com/Z3Prover/z3
synced 2025-04-24 01:25:31 +00:00
recfun
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
fac114872f
commit
aa6e1badf2
9 changed files with 95 additions and 33 deletions
|
@ -96,5 +96,6 @@ def_module_params(module_name='smt',
|
|||
('core.extend_nonlocal_patterns', BOOL, False, 'extend unsat cores with literals that have quantifiers with patterns that contain symbols which are not in the quantifier\'s body'),
|
||||
('lemma_gc_strategy', UINT, 0, 'lemma garbage collection strategy: 0 - fixed, 1 - geometric, 2 - at restart, 3 - none'),
|
||||
('dt_lazy_splits', UINT, 1, 'How lazy datatype splits are performed: 0- eager, 1- lazy for infinite types, 2- lazy'),
|
||||
('recfun.native', BOOL, False, 'use native rec-fun solver')
|
||||
('recfun.native', BOOL, False, 'use native rec-fun solver'),
|
||||
('recfun.depth', UINT, 2, 'initial depth for maxrec expansion')
|
||||
))
|
||||
|
|
|
@ -1384,7 +1384,10 @@ namespace smt {
|
|||
SASSERT(m_manager.is_eq(n));
|
||||
expr * lhs = n->get_arg(0);
|
||||
expr * rhs = n->get_arg(1);
|
||||
if (val == l_true) {
|
||||
if (m_manager.is_bool(lhs)) {
|
||||
// no-op
|
||||
}
|
||||
else if (val == l_true) {
|
||||
add_eq(get_enode(lhs), get_enode(rhs), eq_justification(l));
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -303,7 +303,7 @@ namespace smt {
|
|||
for (bool_var v = 0; v < num; v++) {
|
||||
if (has_enode(v)) {
|
||||
enode * n = bool_var2enode(v);
|
||||
if (n->is_eq() && is_relevant(n) && get_assignment(v) == l_false) {
|
||||
if (n->is_eq() && is_relevant(n) && get_assignment(v) == l_false && !m_manager.is_iff(n->get_owner())) {
|
||||
TRACE("check_th_diseq_propagation", tout << "checking: #" << n->get_owner_id() << " " << mk_bounded_pp(n->get_owner(), m_manager) << "\n";);
|
||||
enode * lhs = n->get_arg(0)->get_root();
|
||||
enode * rhs = n->get_arg(1)->get_root();
|
||||
|
|
|
@ -50,7 +50,14 @@ namespace smt {
|
|||
return alloc(theory_recfun, new_ctx->get_manager());
|
||||
}
|
||||
|
||||
void theory_recfun::init_search_eh() {
|
||||
smt_params_helper p(ctx().get_params());
|
||||
m_max_depth = p.recfun_depth();
|
||||
}
|
||||
|
||||
|
||||
bool theory_recfun::internalize_atom(app * atom, bool gate_ctx) {
|
||||
TRACEFN(mk_pp(atom, m));
|
||||
for (expr * arg : *atom) {
|
||||
ctx().internalize(arg, false);
|
||||
}
|
||||
|
@ -76,7 +83,13 @@ namespace smt {
|
|||
}
|
||||
|
||||
void theory_recfun::reset_queues() {
|
||||
for (auto* e : m_q_case_expand) {
|
||||
dealloc(e);
|
||||
}
|
||||
m_q_case_expand.reset();
|
||||
for (auto* e : m_q_body_expand) {
|
||||
dealloc(e);
|
||||
}
|
||||
m_q_body_expand.reset();
|
||||
m_q_clauses.clear();
|
||||
}
|
||||
|
@ -96,8 +109,7 @@ namespace smt {
|
|||
SASSERT(ctx().relevancy());
|
||||
if (u().is_defined(n)) {
|
||||
TRACEFN("relevant_eh: (defined) " << mk_pp(n, m));
|
||||
case_expansion e(u(), n);
|
||||
push_case_expand(std::move(e));
|
||||
push_case_expand(alloc(case_expansion, u(), n));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -114,11 +126,13 @@ namespace smt {
|
|||
|
||||
// restore depth book-keeping
|
||||
unsigned new_lim = m_preds_lim.size()-num_scopes;
|
||||
#if 0
|
||||
unsigned start = m_preds_lim[new_lim];
|
||||
for (unsigned i = start; i < m_preds.size(); ++i) {
|
||||
m_pred_depth.remove(m_preds.get(i));
|
||||
}
|
||||
m_preds.resize(start);
|
||||
#endif
|
||||
m_preds_lim.shrink(new_lim);
|
||||
}
|
||||
|
||||
|
@ -141,25 +155,31 @@ namespace smt {
|
|||
ctx().mk_th_axiom(get_id(), c);
|
||||
}
|
||||
m_q_clauses.clear();
|
||||
|
||||
|
||||
for (unsigned i = 0; i < m_q_case_expand.size(); ++i) {
|
||||
case_expansion & e = m_q_case_expand[i];
|
||||
if (e.m_def->is_fun_macro()) {
|
||||
case_expansion* e = m_q_case_expand[i];
|
||||
if (e->m_def->is_fun_macro()) {
|
||||
// body expand immediately
|
||||
assert_macro_axiom(e);
|
||||
assert_macro_axiom(*e);
|
||||
}
|
||||
else {
|
||||
// case expand
|
||||
SASSERT(e.m_def->is_fun_defined());
|
||||
assert_case_axioms(e);
|
||||
SASSERT(e->m_def->is_fun_defined());
|
||||
assert_case_axioms(*e);
|
||||
}
|
||||
dealloc(e);
|
||||
m_q_case_expand[i] = nullptr;
|
||||
}
|
||||
m_q_case_expand.clear();
|
||||
m_stats.m_case_expansions += m_q_case_expand.size();
|
||||
m_q_case_expand.reset();
|
||||
|
||||
for (unsigned i = 0; i < m_q_body_expand.size(); ++i) {
|
||||
assert_body_axiom(m_q_body_expand[i]);
|
||||
assert_body_axiom(*m_q_body_expand[i]);
|
||||
dealloc(m_q_body_expand[i]);
|
||||
m_q_body_expand[i] = nullptr;
|
||||
}
|
||||
m_q_body_expand.clear();
|
||||
m_stats.m_body_expansions += m_q_body_expand.size();
|
||||
m_q_body_expand.reset();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -167,7 +187,6 @@ namespace smt {
|
|||
* the guard appears at a depth below the current cutoff.
|
||||
*/
|
||||
void theory_recfun::assert_max_depth_limit(expr* guard) {
|
||||
TRACEFN("max-depth limit");
|
||||
literal_vector c;
|
||||
app_ref dlimit = m_util.mk_depth_limit_pred(m_max_depth);
|
||||
c.push_back(~mk_literal(dlimit));
|
||||
|
@ -216,8 +235,7 @@ namespace smt {
|
|||
if (is_true && u().is_case_pred(e)) {
|
||||
TRACEFN("assign_case_pred_true " << mk_pp(e, m));
|
||||
// body-expand
|
||||
body_expansion b_e(u(), to_app(e));
|
||||
push_body_expand(std::move(b_e));
|
||||
push_body_expand(alloc(body_expansion, u(), to_app(e)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -268,6 +286,7 @@ namespace smt {
|
|||
* 2. add unit clause `f(args) = rhs`
|
||||
*/
|
||||
void theory_recfun::assert_macro_axiom(case_expansion & e) {
|
||||
m_stats.m_macro_expansions++;
|
||||
TRACEFN("case expansion " << pp_case_expansion(e, m) << "\n");
|
||||
SASSERT(e.m_def->is_fun_macro());
|
||||
auto & vars = e.m_def->get_vars();
|
||||
|
@ -381,6 +400,7 @@ namespace smt {
|
|||
for (auto & e : unsat_core) {
|
||||
if (u().is_depth_limit(e)) {
|
||||
m_max_depth = (3 * m_max_depth) / 2;
|
||||
IF_VERBOSE(1, verbose_stream() << "(smt.recfun :increase-depth " << m_max_depth << ")\n");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -101,8 +101,8 @@ namespace smt {
|
|||
unsigned_vector m_preds_lim;
|
||||
unsigned m_max_depth; // for fairness and termination
|
||||
|
||||
vector<case_expansion> m_q_case_expand;
|
||||
vector<body_expansion> m_q_body_expand;
|
||||
ptr_vector<case_expansion> m_q_case_expand;
|
||||
ptr_vector<body_expansion> m_q_body_expand;
|
||||
vector<literal_vector> m_q_clauses;
|
||||
|
||||
recfun_util & u() const { return m_util; }
|
||||
|
@ -128,8 +128,8 @@ namespace smt {
|
|||
return vars.size() == 0 || vars[vars.size()-1]->get_idx() == 0;
|
||||
}
|
||||
protected:
|
||||
void push_case_expand(case_expansion&& e) { m_q_case_expand.push_back(e); }
|
||||
void push_body_expand(body_expansion&& e) { m_q_body_expand.push_back(e); }
|
||||
void push_case_expand(case_expansion* e) { m_q_case_expand.push_back(e); }
|
||||
void push_body_expand(body_expansion* e) { m_q_body_expand.push_back(e); }
|
||||
|
||||
bool internalize_atom(app * atom, bool gate_ctx) override;
|
||||
bool internalize_term(app * term) override;
|
||||
|
@ -153,7 +153,7 @@ namespace smt {
|
|||
theory_recfun(ast_manager & m);
|
||||
~theory_recfun() override;
|
||||
theory * mk_fresh(context * new_ctx) override;
|
||||
void init_search_eh() override { m_max_depth = 2; }
|
||||
void init_search_eh() override;
|
||||
void display(std::ostream & out) const override;
|
||||
void collect_statistics(::statistics & st) const override;
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue