3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-22 16:45:31 +00:00

Reorganizing the code

Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
Leonardo de Moura 2012-10-20 22:28:22 -07:00
parent 492484c5aa
commit aa949693d4
13 changed files with 0 additions and 78 deletions

View file

@ -0,0 +1,208 @@
/*++
Copyright (c) 2010 Microsoft Corporation
Module Name:
array_property_expander.cpp
Abstract:
Expand array operations for the array property fragment formulas.
Author:
Nikolaj Bjorner (nbjorner) 2010-16-12
Revision History:
--*/
#include"array_property_expander.h"
#include"obj_hashtable.h"
#include"var_subst.h"
#include"array_decl_plugin.h"
#include"for_each_expr.h"
array_property_expander::array_property_expander(ast_manager& m):
m_manager(m) {
}
namespace array_property_exp {
class proc {
ast_manager& m_manager;
unsigned& m_offset;
expr_ref_vector m_trail;
family_id m_fid;
array_util m_util;
obj_map<expr, expr*> m_mem;
void insert(expr* a, expr* b) {
m_trail.push_back(b);
m_mem.insert(a, b);
}
public:
proc(ast_manager& m, unsigned& offset) :
m_manager(m),
m_offset(offset),
m_trail(m),
m_fid(m.get_family_id("array")),
m_util(m)
{}
expr* find(expr* e) {
expr* result = 0;
VERIFY(m_mem.find(e, result));
return result;
}
void operator()(var* n) { insert(n, n); }
void operator()(quantifier* q) {
expr* e = find(q->get_expr());
quantifier* q2 = m_manager.update_quantifier(q, e);
insert(q, q2);
}
void operator()(app* n) {
ast_manager& m = m_manager;
unsigned num_args = n->get_num_args();
ptr_buffer<expr> args;
for (unsigned i = 0; i < num_args; ++i) {
args.push_back(find(n->get_arg(i)));
}
if (m_manager.is_eq(n) && m_util.is_array(args[0])) {
visit_eq(n);
return;
}
if (m_manager.is_distinct(n) && num_args > 0 && m_util.is_array(args[0])) {
ptr_buffer<expr> eqs;
for (unsigned i = 0; i < num_args; ++i) {
for (unsigned j = i + 1; j < num_args; ++j) {
eqs.push_back(m.mk_not(m.mk_eq(args[i], args[j])));
}
}
insert(n, m.mk_and(eqs.size(), eqs.c_ptr()));
return;
}
if (m_util.is_select(n)) {
SASSERT(num_args > 0);
// select(store(A,i,v),j) -> ite(i = j, v, select(A,j))
if (m_util.is_store(args[0])) {
app* a = to_app(args[0]);
expr* b = find(a->get_arg(0));
expr* v = find(a->get_arg(a->get_num_args()-1));
ptr_buffer<expr> eqs;
SASSERT(num_args + 1 == a->get_num_args());
for (unsigned i = 1; i < num_args; ++i) {
eqs.push_back(m.mk_eq(args[i], find(a->get_arg(i))));
}
expr* r = m.mk_ite(m.mk_and(eqs.size(), eqs.c_ptr()), v, mk_select(b, num_args-1, args.c_ptr()+1));
insert(n, r);
return;
}
// select(ite(a,b,c),i) -> ite(a, select(b,i), select(c, i))
if (m.is_ite(args[0])) {
app* k = to_app(args[0]);
expr* a = k->get_arg(0);
expr* b = mk_select(k->get_arg(1), args.size()-1, args.c_ptr()+1);
expr* c = mk_select(k->get_arg(2), args.size()-1, args.c_ptr()+1);
expr* r = m.mk_ite(a, b, c);
insert(n, r);
return;
}
// select(map_f(A,B),i) -> f(select(A,i), select(B,i))
if (m_util.is_map(args[0])) {
app* a = to_app(args[0]);
func_decl* f = a->get_decl();
SASSERT(f->get_num_parameters() == 1);
SASSERT(f->get_parameter(0).is_ast());
SASSERT(is_func_decl(f->get_parameter(0).get_ast()));
parameter p = f->get_parameter(0);
func_decl* d = to_func_decl(p.get_ast());
ptr_buffer<expr> args2;
for (unsigned i = 0; i < a->get_num_args(); ++i) {
args2.push_back(mk_select(find(a->get_arg(i)), args.size()-1, args.c_ptr()+1));
}
expr* r = m.mk_app(d, args2.size(), args2.c_ptr());
insert(n, r);
return;
}
// select(const v, i) -> v
if (m_util.is_const(args[0])) {
insert(n, to_app(args[0])->get_arg(0));
return;
}
}
expr* r = m_manager.mk_app(n->get_decl(), args.size(), args.c_ptr());
insert(n, r);
}
private:
void visit_eq(app* eq) {
ast_manager& m = m_manager;
SASSERT(m.is_eq(eq));
sort* s = m.get_sort(eq->get_arg(0));
SASSERT(is_sort_of(s, m_fid, ARRAY_SORT));
// sort* rng = get_array_range(s);
unsigned arity = get_array_arity(s);
shift_vars sh(m);
expr_ref e1(m), e2(m);
sh(find(eq->get_arg(0)), arity, e1);
sh(find(eq->get_arg(1)), arity, e2);
expr_ref_vector args(m);
buffer<symbol> names;
ptr_buffer<sort> sorts;
args.push_back(e1);
for (unsigned i = 0; i < arity; ++i) {
args.push_back(m.mk_var(i, get_array_domain(s, i)));
sorts.push_back(get_array_domain(s, arity - i - 1));
names.push_back(symbol(m_offset++));
}
e1 = mk_select(args.size(), args.c_ptr());
args[0] = e2;
e2 = mk_select(args.size(), args.c_ptr());
e1 = m.mk_eq(e1, e2);
e1 = m.mk_quantifier(true, arity, sorts.c_ptr(), names.c_ptr(), e1, 1);
insert(eq, e1);
}
app* mk_select(unsigned n, expr* const* args) {
return m_manager.mk_app(m_fid, OP_SELECT, 0, 0, n, args);
}
app* mk_select(expr* a, unsigned n, expr* const* args) {
ptr_buffer<expr> args2;
args2.push_back(a);
args2.append(n, args);
return mk_select(n+1, args2.c_ptr());
}
};
};
void array_property_expander::operator()(unsigned num_fmls, expr* const* fmls, expr_ref_vector& result) {
ast_manager& m = m_manager;
unsigned offset = 0;
for (unsigned i = 0; i < num_fmls; ++i) {
bool change = false;
expr_ref e(m);
result.push_back(fmls[i]);
do {
array_property_exp::proc p(m, offset);
e = result[i].get();
for_each_expr(p, e);
result[i] = p.find(e);
change = e != result[i].get();
}
while (change);
}
}

View file

@ -0,0 +1,33 @@
/*++
Copyright (c) 2010 Microsoft Corporation
Module Name:
array_property_expander.h
Abstract:
Expand array operations for the array property fragment formulas.
Author:
Nikolaj Bjorner (nbjorner) 2010-16-12
Revision History:
--*/
#ifndef _ARRAY_PROPERTY_EXPANDER_H_
#define _ARRAY_PROPERTY_EXPANDER_H_
#include"ast.h"
class array_property_expander {
ast_manager& m_manager;
public:
array_property_expander(ast_manager& m);
void operator()(unsigned num_fmls, expr* const* fmls, expr_ref_vector& result);
};
#endif /* _ARRAY_PROPERTY_EXPANDER_H_ */

View file

@ -0,0 +1,103 @@
/*++
Copyright (c) 2010 Microsoft Corporation
Module Name:
array_property_recognizer.cpp
Abstract:
<abstract>
Author:
Nikolaj Bjorner (nbjorner) 2010-16-12
Revision History:
--*/
#include"array_decl_plugin.h"
#include"array_property_recognizer.h"
#include"for_each_expr.h"
array_property_recognizer::array_property_recognizer(ast_manager& m):
m_manager(m) {}
namespace is_array_property_ns {
struct bad {};
class proc {
ast_manager& m_manager;
family_id m_fid;
bool m_has_quantifier;
void check_array_sort(expr* n) {
if (is_sort_of(m_manager.get_sort(n), m_fid, ARRAY_SORT)) {
throw bad();
}
}
public:
proc(ast_manager& m) :
m_manager(m),
m_fid(m.get_family_id("array")),
m_has_quantifier(false) {}
bool has_quantifier() const { return m_has_quantifier; }
void operator()(var* n) {
check_array_sort(n);
}
void operator()(quantifier * ) {
m_has_quantifier = true;
}
void operator()(app* n) {
unsigned num_args = n->get_num_args();
if (m_manager.is_eq(n) || m_manager.is_distinct(n)) {
return;
}
family_id fid = n->get_family_id();
if (fid == m_fid) {
switch(n->get_decl_kind()) {
case OP_STORE:
for (unsigned i = 1; i + 1 < num_args; ++i) {
check_array_sort(n->get_arg(i));
}
return;
case OP_SELECT:
for (unsigned i = 1; i < num_args; ++i) {
check_array_sort(n->get_arg(i));
}
return;
case OP_CONST_ARRAY:
case OP_ARRAY_MAP:
return;
default:
throw bad();
}
}
// arrays cannot be arguments of other functions.
for (unsigned i = 0; i < num_args; ++i) {
check_array_sort(n->get_arg(i));
}
}
};
};
bool array_property_recognizer::operator()(unsigned num_fmls, expr* const* fmls) {
is_array_property_ns::proc p(m_manager);
try {
for (unsigned i = 0; i < num_fmls; ++i) {
for_each_expr(p, fmls[i]);
}
}
catch (is_array_property_ns::bad) {
return false;
}
return p.has_quantifier();
}

View file

@ -0,0 +1,33 @@
/*++
Copyright (c) 2010 Microsoft Corporation
Module Name:
array_property_recognizer.h
Abstract:
<abstract>
Author:
Nikolaj Bjorner (nbjorner) 2010-16-12
Revision History:
--*/
#ifndef _ARRAY_PROPERTY_RECOGNIZER_H_
#define _ARRAY_PROPERTY_RECOGNIZER_H_
#include"ast.h"
class array_property_recognizer {
ast_manager& m_manager;
public:
array_property_recognizer(ast_manager& m);
bool operator()(unsigned num_fmls, expr* const* fmls);
};
#endif /* _ARRAY_PROPERTY_RECOGNIZER_H_ */

33
src/dead/big_rational.h Normal file
View file

@ -0,0 +1,33 @@
/*++
Copyright (c) 2006 Microsoft Corporation
Module Name:
big_rational.h
Abstract:
Big rational numbers
Author:
Leonardo de Moura (leonardo) 2006-09-18.
Revision History:
--*/
#ifndef _BIG_RATIONAL_H_
#define _BIG_RATIONAL_H_
#ifdef _WINDOWS
#include"..\msbig_rational\msbig_rational.h"
#else
#ifdef NO_GMP
#include"dummy_big_rational.h"
#else
#include"gmp_big_rational.h"
#endif
#endif
#endif /* _BIG_RATIONAL_H_ */

View file

@ -0,0 +1,54 @@
/*++
Copyright (c) 2006 Microsoft Corporation
Module Name:
dummy_big_rational.h
Abstract:
Dummy big rational
Author:
Leonardo de Moura (leonardo) 2006-09-26.
Revision History:
--*/
#ifndef _DUMMY_BIG_RATIONAL_H_
#define _DUMMY_BIG_RATIONAL_H_
#include<string>
#include"debug.h"
class big_rational {
public:
big_rational() { }
big_rational(int n) {}
~big_rational() {}
void reset() {}
unsigned hash() const { return 0; }
void set(int num, int den) { UNREACHABLE(); }
void set(const char * str) { UNREACHABLE(); }
bool is_int() const { UNREACHABLE(); return false; }
long get_int() const { UNREACHABLE(); return 0; }
void neg() { UNREACHABLE(); }
big_rational & operator=(const big_rational & r) { UNREACHABLE(); return *this; }
bool operator==(const big_rational & r) const { UNREACHABLE(); return false; }
bool operator<(const big_rational & r) const { UNREACHABLE(); return false; }
big_rational & operator+=(const big_rational & r) { UNREACHABLE(); return *this; }
big_rational & operator-=(const big_rational & r) { UNREACHABLE(); return *this; }
big_rational & operator*=(const big_rational & r) { UNREACHABLE(); return *this; }
big_rational & operator/=(const big_rational & r) { UNREACHABLE(); return *this; }
big_rational & operator%=(const big_rational & r) { UNREACHABLE(); return *this; }
friend void div(const big_rational & r1, const big_rational & r2, big_rational & result) { UNREACHABLE(); }
void get_numerator(big_rational & result) { UNREACHABLE(); }
void get_denominator(big_rational & result) { UNREACHABLE(); }
void get_floor(big_rational & result) { UNREACHABLE(); }
std::string to_string() const { UNREACHABLE(); return std::string(""); }
};
#endif /* _DUMMY_BIG_RATIONAL_H_ */

1047
src/dead/gl_tactic.cpp Normal file

File diff suppressed because it is too large Load diff

29
src/dead/gl_tactic.h Normal file
View file

@ -0,0 +1,29 @@
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
gl_tactic.h
Abstract:
A T-function/Goldreich Levin-based heuristic.
Author:
Nikolaj (nbjorner) 2011-12-18
Notes:
--*/
#ifndef _GL_TACTIC_H_
#define _GL_TACTIC_H_
#include"tactic.h"
namespace gl {
tactic * mk_tactic(ast_manager& m, params_ref const& p);
};
#endif

View file

@ -0,0 +1,117 @@
/*++
Copyright (c) 2006 Microsoft Corporation
Module Name:
gmp_big_rational.cpp
Abstract:
Big rationals using GMP
Author:
Leonardo de Moura (leonardo) 2006-09-26.
Revision History:
--*/
#include<limits.h>
#include"gmp_big_rational.h"
#include"trace.h"
#include"buffer.h"
#ifndef NO_GMP
mpz_t big_rational::m_tmp;
bool big_rational::m_tmp_initialized = false;
mpz_t big_rational::m_int_min;
mpz_t big_rational::m_int_max;
mpz_t big_rational::m_uint_max;
mpz_t big_rational::m_two32;
mpz_t big_rational::m_int64_min;
mpz_t big_rational::m_int64_max;
mpz_t big_rational::m_uint64_max;
bool big_rational::m_has_limits = false;
void big_rational::init_limits() {
mpz_init(m_int_min);
mpz_init(m_int_max);
mpz_init(m_uint_max);
mpz_init(m_two32);
mpz_init(m_int64_min);
mpz_init(m_int64_max);
mpz_init(m_uint64_max);
mpz_set_si(m_int_min, INT_MIN);
mpz_set_si(m_int_max, INT_MAX);
mpz_set_ui(m_uint_max, UINT_MAX);
mpz_set_ui(m_two32, UINT_MAX);
mpz_t & tmp = get_tmp();
mpz_set_si(tmp, 1);
mpz_add(m_two32, m_two32, tmp);
unsigned max_l = static_cast<unsigned>(INT64_MAX % static_cast<int64>(UINT_MAX));
unsigned max_h = static_cast<unsigned>(INT64_MAX / static_cast<int64>(UINT_MAX));
mpz_set_ui(m_int64_max, max_h);
mpz_mul(m_int64_max, m_uint_max, m_int64_max);
mpz_set_ui(tmp, max_l);
mpz_add(m_int64_max, tmp, m_int64_max);
mpz_neg(m_int64_min, m_int64_max);
mpz_set_si(tmp, -1);
mpz_add(m_int64_min, m_int64_min, tmp);
mpz_set(m_uint64_max, m_int64_max);
mpz_set_si(tmp, 2);
mpz_mul(m_uint64_max, m_uint64_max, tmp);
mpz_set_si(tmp, 1);
mpz_add(m_uint64_max, m_uint64_max, tmp);
m_has_limits = true;
}
std::string big_rational::to_string() const {
size_t sz = mpz_sizeinbase(mpq_numref(m_data), 10) + mpz_sizeinbase(mpq_numref(m_data), 10) + 3;
buffer<char> b(sz, 0);
mpq_get_str(b.c_ptr(), 10, m_data);
std::string result(b.c_ptr());
return result;
}
int64 big_rational::get_int64() const {
if (!m_has_limits) {
init_limits();
}
SASSERT(is_int64());
mpz_t & tmp = get_tmp();
mpq_get_num(tmp, m_data);
if (sizeof(int64) == sizeof(long) || mpz_fits_slong_p(tmp)) {
return mpz_get_si(tmp);
}
else {
mpz_mod(tmp, tmp, two32());
int64 r = static_cast<int64>(mpz_get_ui(tmp));
mpq_get_num(tmp, m_data);
mpz_div(tmp, tmp, two32());
r += static_cast<int64>(mpz_get_si(tmp)) << static_cast<int64>(32);
return r;
}
}
uint64 big_rational::get_uint64() const {
if (!m_has_limits) {
init_limits();
}
SASSERT(is_uint64());
mpz_t & tmp = get_tmp();
mpq_get_num(tmp, m_data);
if (sizeof(uint64) == sizeof(unsigned long) || mpz_fits_ulong_p(tmp)) {
return mpz_get_ui(tmp);
}
else {
mpz_mod(tmp, tmp, two32());
uint64 r = static_cast<uint64>(mpz_get_ui(tmp));
mpq_get_num(tmp, m_data);
mpz_div(tmp, tmp, two32());
r += static_cast<uint64>(mpz_get_ui(tmp)) << static_cast<uint64>(32);
return r;
}
}
#endif

193
src/dead/gmp_big_rational.h Normal file
View file

@ -0,0 +1,193 @@
/*++
Copyright (c) 2006 Microsoft Corporation
Module Name:
gmp_big_rational.h
Abstract:
Big rationals using gmp
Author:
Leonardo de Moura (leonardo) 2006-09-26.
Revision History:
--*/
#ifndef _GMP_BIG_RATIONAL_H_
#define _GMP_BIG_RATIONAL_H_
#ifndef NO_GMP
#include<string>
#include<gmp.h>
#include"util.h"
#include"debug.h"
#include"trace.h"
class big_rational {
mpq_t m_data;
static mpz_t m_tmp;
static bool m_tmp_initialized;
static mpz_t & get_tmp() {
if (!m_tmp_initialized) {
mpz_init(m_tmp);
m_tmp_initialized = true;
}
return m_tmp;
}
static mpz_t m_int_min;
static mpz_t m_int_max;
static mpz_t m_uint_max;
static mpz_t m_two32;
static mpz_t m_int64_min;
static mpz_t m_int64_max;
static mpz_t m_uint64_max;
static bool m_has_limits;
static void init_limits();
static mpz_t & int64_min() {
if (!m_has_limits) {
init_limits();
}
return m_int64_min;
}
static mpz_t & int64_max() {
if (!m_has_limits) {
init_limits();
}
return m_int64_max;
}
static mpz_t & uint64_max() {
if (!m_has_limits) {
init_limits();
}
return m_uint64_max;
}
static mpz_t & uint_max() {
if (!m_has_limits) {
init_limits();
}
return m_uint_max;
}
static mpz_t & two32() {
if (!m_has_limits) {
init_limits();
}
return m_two32;
}
public:
big_rational() { mpq_init(m_data); reset(); }
big_rational(int n) { mpq_init(m_data); mpq_set_si(m_data, n, 1); }
~big_rational() { mpq_clear(m_data); }
void reset() { mpq_set_si(m_data, 0, 1); }
unsigned hash() const { return mpz_get_si(mpq_numref(m_data)); }
void set(int num, int den) {
mpq_set_si(m_data, num, den);
mpq_canonicalize(m_data);
}
void setu(unsigned num) {
mpq_set_ui(m_data, num, 1);
mpq_canonicalize(m_data);
}
void set(const char * str) {
mpq_set_str(m_data, str, 10);
}
bool is_int() const {
return mpz_cmp_ui(mpq_denref(m_data), 1) == 0;
}
bool is_even() const {
if (!is_int()) {
return false;
}
mpz_t & tmp = get_tmp();
mpq_get_num(tmp, m_data);
return mpz_even_p(tmp) != 0;
}
bool is_int64() const {
if (!is_int()) {
return false;
}
mpz_t & tmp = get_tmp();
mpq_get_num(tmp, m_data);
return mpz_fits_slong_p(tmp) ||
(mpz_cmp(tmp, int64_min()) >= 0 && mpz_cmp(tmp, int64_max()) <= 0);
}
bool is_uint64() const {
if (!is_int()) {
return false;
}
mpz_t & tmp = get_tmp();
mpq_get_num(tmp, m_data);
return mpz_sgn(tmp) >= 0 && (mpz_fits_ulong_p(tmp) || mpz_cmp(tmp, uint64_max()) <= 0);
}
int64 get_int64() const;
uint64 get_uint64() const;
void neg() { mpq_neg(m_data, m_data); }
big_rational & operator=(const big_rational & r) {
mpq_set(m_data, r.m_data);
return *this;
}
bool operator==(const big_rational & r) const { return mpq_equal(m_data, r.m_data) != 0; }
bool operator<(const big_rational & r) const { return mpq_cmp(m_data, r.m_data) < 0; }
big_rational & operator+=(const big_rational & r) {
mpq_add(m_data, m_data, r.m_data);
return *this;
}
big_rational & operator-=(const big_rational & r) {
mpq_sub(m_data, m_data, r.m_data);
return *this;
}
big_rational & operator*=(const big_rational & r) {
mpq_mul(m_data, m_data, r.m_data);
return *this;
}
big_rational & operator/=(const big_rational & r) {
mpq_div(m_data, m_data, r.m_data);
return *this;
}
big_rational & operator%=(const big_rational & r) {
mpz_t & tmp = get_tmp();
mpz_tdiv_r(tmp, mpq_numref(m_data), mpq_numref(r.m_data));
mpq_set_z(m_data, tmp);
return *this;
}
friend void div(const big_rational & r1, const big_rational & r2, big_rational & result) {
mpz_t & tmp = get_tmp();
mpz_tdiv_q(tmp, mpq_numref(r1.m_data), mpq_numref(r2.m_data));
mpq_set_z(result.m_data, tmp);
}
void get_numerator(big_rational & result) {
mpz_t & tmp = get_tmp();
mpq_get_num(tmp, m_data);
mpq_set_z(result.m_data, tmp);
}
void get_denominator(big_rational & result) {
mpz_t & tmp = get_tmp();
mpq_get_den(tmp, m_data);
mpq_set_z(result.m_data, tmp);
}
void get_floor(big_rational & result) {
mpz_t & tmp = get_tmp();
mpz_fdiv_q(tmp, mpq_numref(m_data), mpq_denref(m_data));
mpq_set_z(result.m_data, tmp);
}
std::string to_string() const;
#ifdef Z3DEBUG
static void test() {
init_limits();
}
#endif
};
#endif
#endif /* _GMP_BIG_RATIONAL_H_ */

View file

@ -0,0 +1,26 @@
/*++
Copyright (c) 2006 Microsoft Corporation
Module Name:
arith_simplifier_params.cpp
Abstract:
<abstract>
Author:
Leonardo de Moura (leonardo) 2008-05-09.
Revision History:
--*/
#include"arith_simplifier_params.h"
void arith_simplifier_params::register_params(ini_params & p) {
p.register_bool_param("ARITH_EXPAND_EQS", m_arith_expand_eqs);
p.register_bool_param("ARITH_PROCESS_ALL_EQS", m_arith_process_all_eqs);
}

145
src/rewriter/rewriter.txt Normal file
View file

@ -0,0 +1,145 @@
The following classes implement theory specific rewriting rules:
- bool_rewriter
- arith_rewriter
- bv_rewriter
- array_rewriter
- datatype_rewriter
Each of the provide the method
br_status mk_app_core(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result)
where
- f is expected to be a func_decl of the given theory
- If the return value if different from BR_FAILED, the result is stored in result.
The template rewriter_tpl<Cfg> can be instantiated to implement
rewriters that traverse ASTs applying some kind of transformation/simplification.
The parameter Cfg is expected to be a class with the following methods:
bool cache_all_results() const;
bool cache_results() const;
bool flat_assoc(func_decl * f) const;
bool rewrite_patterns() const;
bool max_scopes_exceeded(unsigned num_scopes) const;
bool max_frames_exceeded(unsigned num_frames) const;
bool max_steps_exceeded(unsigned num_steps) const;
bool pre_visit(expr * t);
br_status reduce_app(func_decl * f, unsigned num, expr * const * args, expr_ref & result, proof_ref & result_pr);
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);
bool get_macro(func_decl * d, expr * & def, quantifier * & q, proof * & def_pr);
bool get_subst(expr * s, expr * & t, proof * & t_pr);
void reset();
void cleanup();
The class default_rewriter_cfg provides a default implementation for these methods.
The method reduce_app is the most important one. When implementing new rewriter,
we usually redefine this method.
We should return BR_FAILED, if we do not want to apply a "simplification" to
(f args[0] ... args[num-1])
This is very important for performance reasons, since the rewriter tries to
reuse AST when BR_FAILED is returned.
If one wants to simply (f args[0] ... args[num-1]) to t, then use:
result = t;
return BR_DONE;
Sometimes, by applying a simplification rule we may create new opportunites for
rewriting. One can instruct the rewriter to revisit the result by returning:
BR_REWRITE1, // rewrite the result (bounded by depth 1)
BR_REWRITE2, // rewrite the result (bounded by depth 2)
BR_REWRITE3, // rewrite the result (bounded by depth 3)
BR_REWRITE_FULL, // rewrite the result unbounded
Example:
Suppose one wants to implement the rewriting rule
(= (ite c t e) v) --> (ite c (= t v) (= e v))
This rule may create new opportunites for simplification since
it creates the equalities (= t v) and (= e v).
So, to force the rewriter to process these new equalities,
BR_REWRITE2 should be returned.
It is also correct (but unnecessary) to return BR_REWRITE3 and BR_REWRITE_FULL.
To instantiate a new rewriter, one should
1) Define a new configuration class.
class mycfg : public default_rewriter_cfg {
...
}
2) Force template instantiation using the new cfg.
templace class rewriter_tpl<mycfg>;
3) Define a subclass of rewriter_tpl<mycfg> that
owns the new cfg.
class myrewriter : public rewriter_tpl<mycfg> {
mycfg m_cfg;
public:
myrewriter(ast_manager & m):
rewriter_tpl<mycfg>(m, m.proofs_enabled(), m_cfg),
m_cfg(...) {
}
};
The rewriter_tpl template supports proof production.
It can be disabled even when proof productions is
enabled in the ast_manager.
Examples of rewriter_tpl instances:
- th_rewriter.cpp
- assertion_set_bit_blaster.cpp
- model_evaluator.cpp
- elim_distinct.cpp
Notes for additional Cfg methods:
- bool rewrite_patterns() const;
If false is returned, then the rewriter will ignore patterns.
- bool pre_visit(expr * t);
If false is returned, then the rewriter will not process t.
This is very useful, for example, for implementing rewriters that will only
"process" the Boolean skeleton.
- bool max_steps_exceeded(unsigned num_steps) const;
If false, it interrupts the execution of the rewriter.
The interruption is performed by throwing an exception.
One can also used this callback to check whether the
amount of memory used is still reasonable.
- bool cache_all_results() const;
By default, the rewriter only caches the results of
non-atomic shared ASTs (get_ref_count() > 1). If true,
is returned, the rewriter will cache all intermediate results.
- bool flat_assoc(func_decl * f) const;
If true is returned, then the rewriter will do flattening of
non-shared nodes. For example,
(+ a (+ b (+ c d)))
will be treated as (+ a b c d)
Shared nodes are not considered. Thus, exponential blowup
in the rewriter stack is avoided.
So, when implementing
br_status reduce_app(func_decl * f, unsigned num, expr * const * args, expr_ref & result, proof_ref & result_pr);
one should not assume that for an associative f, there is not
f-application in args when true is returned by flat_assoc.
when implementing
br_status reduce_app(func_decl * f, unsigned num, expr * const * args, expr_ref & result, proof_ref & result_pr);
If result_pr is set to 0, and proofs are enabled, then the rewriter will use a generic
"rewrite" proof step for justifying that (f args[0] ... args[num-1]) is equal to result.
The th_rewriter takes care of flattening. So, in principle, there is
not need to return true in flat_assoc.