3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-29 11:55:51 +00:00
z3/src/ast/rewriter/value_sweep.cpp
2021-02-02 04:45:54 -08:00

163 lines
3.9 KiB
C++

/*++
Copyright (c) 2020 Microsoft Corporation
Module Name:
value_sweep.cpp
Author:
Nikolaj Bjorner 2020-04-25
--*/
#include "ast/for_each_expr.h"
#include "ast/ast_pp.h"
#include "ast/rewriter/value_sweep.h"
value_sweep::value_sweep(ast_manager& m):
m(m),
m_gen(m),
m_rec(m),
m_dt(m),
m_rewrite(m),
m_values(m),
m_args(m),
m_pinned(m),
m_rounds(10),
m_range(20),
m_qhead(0)
{}
void value_sweep::set_value_core(expr* e, expr* v) {
m_values.reserve(e->get_id() + 1);
m_values[e->get_id()] = v;
}
void value_sweep::set_value(expr* e, expr* v) {
if (!is_reducible(e) || m_dt.is_accessor(e)) {
set_value_core(e, v);
m_pinned.push_back(e);
}
}
void value_sweep::reset_values() {
m_values.reset();
m_pinned.reset();
}
expr* value_sweep::get_value(expr* e) const {
if (m.is_value(e))
return e;
if (m_values.size() <= e->get_id())
return nullptr;
return m_values[e->get_id()];
}
void value_sweep::unassign(unsigned sz) {
for (unsigned i = m_queue.size(); i-- > sz; ) {
expr* e = m_queue[i];
m_values[e->get_id()] = nullptr;
}
m_queue.shrink(sz);
m_qhead = sz;
}
bool value_sweep::assign_next_value() {
for (; m_vhead < m_vars.size(); ) {
expr* v = m_vars[m_vhead];
++m_vhead;
if (!get_value(v)) {
unsigned index = m_rand() % m_range;
expr_ref val = m_gen.get_value(v->get_sort(), index);
set_value_core(v, val);
m_queue.push_back(v);
return true;
}
}
return false;
}
bool value_sweep::is_reducible(expr* e) const {
if (!is_app(e))
return false;
app* a = to_app(e);
return
m_rec.is_defined(a) ||
a->get_family_id() == m_dt.get_family_id() ||
a->get_family_id() == m.get_basic_family_id();
}
bool value_sweep::all_args_have_values(app* p) const {
for (expr* arg : *p) {
if (!get_value(arg))
return false;
}
return true;
}
void value_sweep::propagate_values() {
for (; m_qhead < m_queue.size(); ++m_qhead) {
expr* e = m_queue[m_qhead];
for (app* p : m_parents[e->get_id()]) {
if (get_value(p))
continue;
if (!is_reducible(p))
continue;
if (!all_args_have_values(p))
continue;
m_args.reset();
for (expr* arg : *p)
m_args.push_back(get_value(arg));
expr_ref new_value(m.mk_app(p->get_decl(), m_args), m);
m_rewrite(new_value);
TRACE("value_sweep", tout << "propagate " << mk_pp(p, m) << " " << new_value << "\n";);
set_value_core(p, new_value);
m_queue.push_back(p);
}
}
}
void value_sweep::init(expr_ref_vector const& terms) {
m_parents.reset();
m_queue.reset();
m_vars.reset();
m_qhead = 0;
m_vhead = 0;
for (expr* t : subterms(terms)) {
m_parents.reserve(t->get_id() + 1);
if (get_value(t))
m_queue.push_back(t);
else if (!is_reducible(t))
m_vars.push_back(t);
}
for (expr* t : subterms(terms)) {
if (!is_app(t))
continue;
for (expr* arg : *to_app(t)) {
m_parents[arg->get_id()].push_back(to_app(t));
}
}
}
void value_sweep::operator()(expr_ref_vector const& terms,
vector<expr_ref_vector>& values) {
unsigned qhead0 = m_queue.size();
init(terms);
propagate_values();
unsigned qhead = m_queue.size();
for (unsigned i = 0; i < m_rounds; ++i) {
m_vhead = 0;
while (assign_next_value()) {
propagate_values();
}
expr_ref_vector vec(m);
for (expr* t : terms) {
vec.push_back(get_value(t));
}
values.push_back(vec);
unassign(qhead);
}
unassign(qhead0);
}