mirror of
https://github.com/Z3Prover/z3
synced 2025-04-12 20:18:18 +00:00
150 lines
4.6 KiB
C++
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);
|
|
}
|