3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-13 04:28:17 +00:00
z3/lib/distribute_forall_tactic.cpp
Leonardo de Moura e9eab22e5c Z3 sources
Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
2012-10-02 11:35:25 -07:00

150 lines
4.6 KiB
C++

/*++
Copyright (c) 2012 Microsoft Corporation
Module Name:
distribute_forall_tactic.cpp
Abstract:
<abstract>
Author:
Leonardo de Moura (leonardo) 2012-02-18.
--*/
#include"tactical.h"
#include"rewriter_def.h"
#include"var_subst.h"
class distribute_forall_tactic : public tactic {
struct rw_cfg : public default_rewriter_cfg {
ast_manager & m;
rw_cfg(ast_manager & _m):m(_m) {}
bool reduce_quantifier(quantifier * old_q,
expr * new_body,
expr * const * new_patterns,
expr * const * new_no_patterns,
expr_ref & result,
proof_ref & result_pr) {
if (m.is_not(new_body) && m.is_or(to_app(new_body)->get_arg(0))) {
// (forall X (not (or F1 ... Fn)))
// -->
// (and (forall X (not F1))
// ...
// (forall X (not Fn)))
app * or_e = to_app(to_app(new_body)->get_arg(0));
unsigned num_args = or_e->get_num_args();
expr_ref_buffer new_args(m);
for (unsigned i = 0; i < num_args; i++) {
expr * arg = or_e->get_arg(i);
expr * not_arg = m.mk_not(arg);
quantifier_ref tmp_q(m);
tmp_q = m.update_quantifier(old_q, not_arg);
expr_ref new_q(m);
elim_unused_vars(m, tmp_q, new_q);
new_args.push_back(new_q);
}
result = m.mk_and(new_args.size(), new_args.c_ptr());
return true;
}
if (m.is_and(new_body)) {
// (forall X (and F1 ... Fn))
// -->
// (and (forall X F1)
// ...
// (forall X Fn)
unsigned num_args = to_app(new_body)->get_num_args();
expr_ref_buffer new_args(m);
for (unsigned i = 0; i < num_args; i++) {
expr * arg = to_app(new_body)->get_arg(i);
quantifier_ref tmp_q(m);
tmp_q = m.update_quantifier(old_q, arg);
expr_ref new_q(m);
elim_unused_vars(m, tmp_q, new_q);
new_args.push_back(new_q);
}
result = m.mk_and(new_args.size(), new_args.c_ptr());
return true;
}
return false;
}
};
struct rw : public rewriter_tpl<rw_cfg> {
rw_cfg m_cfg;
rw(ast_manager & m, bool proofs_enabled):
rewriter_tpl<rw_cfg>(m, proofs_enabled, m_cfg),
m_cfg(m) {
}
};
rw * m_rw;
public:
distribute_forall_tactic():m_rw(0) {}
virtual tactic * translate(ast_manager & m) {
return alloc(distribute_forall_tactic);
}
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());
ast_manager & m = g->m();
bool produce_proofs = g->proofs_enabled();
rw r(m, produce_proofs);
#pragma omp critical (tactic_cancel)
{
m_rw = &r;
}
mc = 0; pc = 0; core = 0; result.reset();
tactic_report report("distribute-forall", *g);
expr_ref new_curr(m);
proof_ref new_pr(m);
unsigned size = g->size();
for (unsigned idx = 0; idx < size; idx++) {
if (g->inconsistent())
break;
expr * curr = g->form(idx);
r(curr, new_curr, new_pr);
if (g->proofs_enabled()) {
proof * pr = g->pr(idx);
new_pr = m.mk_modus_ponens(pr, new_pr);
}
g->update(idx, new_curr, new_pr, g->dep(idx));
}
g->inc_depth();
result.push_back(g.get());
TRACE("distribute-forall", g->display(tout););
SASSERT(g->is_well_sorted());
#pragma omp critical (tactic_cancel)
{
m_rw = 0;
}
}
virtual void set_cancel(bool f) {
if (m_rw)
m_rw->set_cancel(f);
}
virtual void cleanup() {}
};
tactic * mk_distribute_forall_tactic(ast_manager & m, params_ref const & p) {
return alloc(distribute_forall_tactic);
}