z3-z3-4.13.0.src.muz.spacer.spacer_sym_mux.cpp Maven / Gradle / Ivy
The newest version!
/*++
Copyright (c) 2018 Arie Gurfinkel and Microsoft Corporation
Module Name:
sym_mux.cpp
Abstract:
A symbol multiplexer that helps with having multiple versions of
each of a set of symbols.
Author:
Arie Gurfinkel
Krystof Hoder (t-khoder) 2011-9-8.
Revision History:
--*/
#include "ast/ast_pp.h"
#include "ast/for_each_expr.h"
#include "ast/rewriter/rewriter.h"
#include "ast/rewriter/rewriter_def.h"
#include "muz/spacer/spacer_util.h"
#include "muz/spacer/spacer_sym_mux.h"
using namespace spacer;
sym_mux::sym_mux(ast_manager & m) : m(m) {}
sym_mux::~sym_mux() {
for (auto &entry : m_entries) {
dealloc(entry.m_value);
}
}
func_decl_ref sym_mux::mk_variant(func_decl *fdecl, unsigned i) const {
func_decl_ref v(m);
std::string name = fdecl->get_name().str();
std::string suffix = "_";
suffix += i == 0 ? "n" : std::to_string(i - 1);
name += suffix;
v = m.mk_func_decl(symbol(name.c_str()), fdecl->get_arity(),
fdecl->get_domain(), fdecl->get_range());
return v;
}
void sym_mux::register_decl(func_decl *fdecl) {
sym_mux_entry *entry = alloc(sym_mux_entry, m);
entry->m_main = fdecl;
entry->m_variants.push_back(mk_variant(fdecl, 0));
entry->m_variants.push_back(mk_variant(fdecl, 1));
m_entries.insert(fdecl, entry);
m_muxes.insert(entry->m_variants.get(0), std::make_pair(entry, 0));
m_muxes.insert(entry->m_variants.get(1), std::make_pair(entry, 1));
}
void sym_mux::ensure_capacity(sym_mux_entry &entry, unsigned sz) const {
while (entry.m_variants.size() < sz) {
unsigned idx = entry.m_variants.size();
entry.m_variants.push_back (mk_variant(entry.m_main, idx));
m_muxes.insert(entry.m_variants.back(), std::make_pair(&entry, idx));
}
}
bool sym_mux::find_idx(func_decl * sym, unsigned & idx) const {
std::pair entry;
if (m_muxes.find(sym, entry)) {idx = entry.second; return true;}
return false;
}
func_decl * sym_mux::find_by_decl(func_decl* fdecl, unsigned idx) const {
sym_mux_entry *entry = nullptr;
if (m_entries.find(fdecl, entry)) {
ensure_capacity(*entry, idx+1);
return entry->m_variants.get(idx);
}
return nullptr;
}
func_decl * sym_mux::shift_decl(func_decl * decl,
unsigned src_idx, unsigned tgt_idx) const {
std::pair entry;
if (m_muxes.find(decl, entry)) {
SASSERT(entry.second == src_idx);
ensure_capacity(*entry.first, tgt_idx + 1);
return entry.first->m_variants.get(tgt_idx);
}
UNREACHABLE();
return nullptr;
}
namespace {
struct formula_checker {
formula_checker(const sym_mux & parent, unsigned idx) :
m_parent(parent), m_idx(idx), m_found(false) {}
void operator()(expr * e) {
if (m_found || !is_app(e)) { return; }
func_decl * sym = to_app(e)->get_decl();
unsigned sym_idx;
if (!m_parent.find_idx(sym, sym_idx)) { return; }
bool have_idx = sym_idx == m_idx;
m_found = !have_idx;
}
bool all_have_idx() const {return !m_found;}
private:
const sym_mux & m_parent;
unsigned m_idx;
bool m_found;
};
}
bool sym_mux::is_homogenous_formula(expr * e, unsigned idx) const {
expr_mark visited;
formula_checker fck(*this, idx);
for_each_expr(fck, visited, e);
return fck.all_have_idx();
}
namespace {
struct conv_rewriter_cfg : public default_rewriter_cfg {
private:
ast_manager & m;
const sym_mux & m_parent;
unsigned m_from_idx;
unsigned m_to_idx;
bool m_homogenous;
expr_ref_vector m_pinned;
public:
conv_rewriter_cfg(const sym_mux & parent, unsigned from_idx,
unsigned to_idx, bool homogenous)
: m(parent.get_manager()),
m_parent(parent),
m_from_idx(from_idx),
m_to_idx(to_idx),
m_homogenous(homogenous), m_pinned(m) {(void) m_homogenous;}
bool get_subst(expr * s, expr * & t, proof * & t_pr)
{
if (!is_app(s))
return false;
app * a = to_app(s);
func_decl * sym = a->get_decl();
if (!m_parent.has_index(sym, m_from_idx)) {
CTRACE("spacer", m_homogenous && m_parent.is_muxed(sym), tout << "not found " << mk_pp(a, m) << "\n");
SASSERT(!m_homogenous || !m_parent.is_muxed(sym));
return false;
}
func_decl * tgt = m_parent.shift_decl(sym, m_from_idx, m_to_idx);
t = m.mk_app(tgt, a->get_args());
m_pinned.push_back(t);
return true;
}
};
}
void sym_mux::shift_expr(expr * f, unsigned src_idx, unsigned tgt_idx,
expr_ref & res, bool homogenous) const {
if (src_idx == tgt_idx) {res = f;}
else {
conv_rewriter_cfg r_cfg(*this, src_idx, tgt_idx, homogenous);
rewriter_tpl rwr(m, false, r_cfg);
rwr(f, res);
}
}