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

233 lines
6.8 KiB
C++

/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
elim_distinct.cpp
Abstract:
Replace one distinct(t0, ..., tn) with (t0 = 0 and ... and tn = n)
when the sort of t0...tn is uninterpreted.
Author:
Leonardo de Moura (leonardo) 2011-04-28
Revision History:
--*/
#include"elim_distinct.h"
#include"assertion_set.h"
#include"model_converter.h"
#include"arith_decl_plugin.h"
#include"rewriter_def.h"
#include"critical_flet.h"
struct elim_distinct::imp {
struct mc : public model_converter {
ast_ref_vector m_asts;
sort * m_usort;
obj_map<func_decl, func_decl *> m_inv_map;
public:
mc(ast_manager & m):m_asts(m) {
}
};
struct u2i_cfg : public default_rewriter_cfg {
arith_util m_autil;
ast_ref_vector m_asts;
sort * m_usort;
sort * m_int_sort;
obj_map<func_decl, func_decl *> m_f2f;
ast_manager & m() const { return m_asts.get_manager(); }
bool must_remap(func_decl * f) const {
if (f->get_range() == m_usort)
return true;
for (unsigned i = 0; i < f->get_arity(); i++) {
if (f->get_domain(i) == m_usort)
return true;
}
return false;
}
sort * remap(sort * s) {
return (s == m_usort) ? m_int_sort : s;
}
func_decl * remap(func_decl * f) {
ptr_buffer<sort> new_domain;
sort * new_range = remap(f->get_range());
for (unsigned i = 0; i < f->get_arity(); i++)
new_domain.push_back(remap(f->get_domain(i)));
func_decl * new_f = m().mk_func_decl(f->get_name(), new_domain.size(), new_domain.c_ptr(), new_range);
m_asts.push_back(new_f);
m_asts.push_back(f);
m_f2f.insert(f, new_f);
return new_f;
}
br_status reduce_app(func_decl * f, unsigned num, expr * const * args, expr_ref & result, proof_ref & result_pr) {
result_pr = 0;
func_decl * new_f;
if (m_f2f.find(f, new_f)) {
result = m().mk_app(new_f, num, args);
return BR_DONE;
}
if (!must_remap(f))
return BR_FAILED;
if (m().is_eq(f)) {
result = m().mk_eq(args[0], args[1]);
return BR_DONE;
}
if (m().is_ite(f)) {
result = m().mk_ite(args[0], args[1], args[2]);
return BR_DONE;
}
if (f->get_family_id() != null_family_id || f->get_info() != 0) {
throw elim_distinct_exception("uninterpreted sort is used in interpreted function symbol");
}
new_f = remap(f);
result = m().mk_app(new_f, num, args);
return BR_DONE;
}
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) {
throw elim_distinct_exception("elim-distinct tactic does not support quantifiers");
}
u2i_cfg(ast_manager & m, sort * u):
m_autil(m),
m_asts(m),
m_usort(u) {
m_asts.push_back(u);
m_int_sort = m_autil.mk_int();
m_asts.push_back(m_int_sort);
}
};
class u2i : public rewriter_tpl<u2i_cfg> {
u2i_cfg m_cfg;
public:
u2i(ast_manager & m, sort * u):
rewriter_tpl<u2i_cfg>(m, false, m_cfg),
m_cfg(m, u) {
if (m.proofs_enabled())
throw elim_distinct_exception("elim-distinct tactic does not support proof generation");
}
arith_util & autil() { return cfg().m_autil; }
};
ast_manager & m_manager;
u2i * m_u2i;
imp(ast_manager & m):m_manager(m), m_u2i(0) {}
ast_manager & m() const { return m_manager; }
bool is_distinct(expr * t) {
if (!m().is_distinct(t))
return false;
if (to_app(t)->get_num_args() == 0)
return false;
return m().is_uninterp(m().get_sort(to_app(t)->get_arg(0)));
}
model_converter * operator()(assertion_set & s, app * d) {
if (d && !is_distinct(d))
d = 0;
app * r = 0;
unsigned sz = s.size();
for (unsigned i = 0; i < sz; i++) {
expr * curr = s.form(i);
if (curr == d)
break;
if (is_distinct(curr)) {
if (!r || to_app(curr)->get_num_args() > r->get_num_args())
r = to_app(curr);
}
}
if (d != 0)
r = d;
if (r == 0)
return 0;
sort * u = m().get_sort(to_app(r)->get_arg(0));
u2i conv(m(), u);
{
critical_flet<u2i*> l1(m_u2i, &conv);
expr_ref new_curr(m());
for (unsigned i = 0; i < sz; i++) {
expr * curr = s.form(i);
if (curr == r) {
unsigned num = r->get_num_args();
for (unsigned j = 0; j < num; j++) {
expr * arg = r->get_arg(j);
conv(arg, new_curr);
expr * eq = m().mk_eq(new_curr, conv.autil().mk_numeral(rational(j), true));
s.assert_expr(eq);
}
new_curr = m().mk_true();
}
else {
conv(curr, new_curr);
}
s.update(i, new_curr);
}
}
// TODO: create model converter
return 0;
}
void cancel() {
// Remark: m_u2i is protected by the omp global critical section.
// If this is a performance problem, then replace critical_flet by a custom flet that uses a different
// section name
#pragma omp critical (critical_flet)
{
if (m_u2i)
m_u2i->cancel();
}
}
};
template class rewriter_tpl<elim_distinct::imp::u2i_cfg>;
elim_distinct::elim_distinct(ast_manager & m) {
m_imp = alloc(imp, m);
}
elim_distinct::~elim_distinct() {
dealloc(m_imp);
}
model_converter * elim_distinct::operator()(assertion_set & s, app * d) {
return m_imp->operator()(s, d);
}
void elim_distinct::cancel() {
m_imp->cancel();
}
void elim_distinct::reset() {
cleanup();
}
void elim_distinct::cleanup() {
ast_manager & m = m_imp->m();
dealloc(m_imp);
m_imp = alloc(imp, m);
}