3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-09-30 21:19:29 +00:00

checkpoint

Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
Leonardo de Moura 2012-10-21 13:32:12 -07:00
parent 4722fdfca5
commit add684d8e9
377 changed files with 204 additions and 62 deletions

77
src/ast/expr2var.cpp Normal file
View file

@ -0,0 +1,77 @@
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
expr2var.h
Abstract:
The mapping between Z3 expressions and (low level) variables.
Example of low level variables:
- SAT solver
- Polynomial
- etc.
Author:
Leonardo (leonardo) 2011-12-23
Notes:
--*/
#include"expr2var.h"
#include"ast_smt2_pp.h"
#include"ref_util.h"
void expr2var::insert(expr * n, var v) {
if (!is_uninterp_const(n)) {
TRACE("expr2var", tout << "interpreted:\n" << mk_ismt2_pp(n, m()) << "\n";);
m_interpreted_vars = true;
}
m().inc_ref(n);
m_mapping.insert(n, v);
m_recent_exprs.push_back(n);
}
expr2var::expr2var(ast_manager & m):
m_manager(m),
m_interpreted_vars(false) {
}
expr2var::~expr2var() {
dec_ref_map_keys(m(), m_mapping);
}
expr2var::var expr2var::to_var(expr * n) const {
var v = UINT_MAX;
m_mapping.find(n, v);
return v;
}
void expr2var::display(std::ostream & out) const {
obj_map<expr, var>::iterator it = m_mapping.begin();
obj_map<expr, var>::iterator end = m_mapping.end();
for (; it != end; ++it) {
out << mk_ismt2_pp(it->m_key, m()) << " -> " << it->m_value << "\n";
}
}
void expr2var::mk_inv(expr_ref_vector & var2expr) const {
obj_map<expr, var>::iterator it = m_mapping.begin();
obj_map<expr, var>::iterator end = m_mapping.end();
for (; it != end; ++it) {
expr * t = it->m_key;
var x = it->m_value;
if (x >= var2expr.size())
var2expr.resize(x+1, 0);
var2expr.set(x, t);
}
}
void expr2var::reset() {
dec_ref_map_keys(m(), m_mapping);
SASSERT(m_mapping.empty());
m_recent_exprs.reset();
m_interpreted_vars = false;
}

75
src/ast/expr2var.h Normal file
View file

@ -0,0 +1,75 @@
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
expr2var.h
Abstract:
The mapping between Z3 expressions and (low level) variables.
Example of low level variables:
- SAT solver
- Polynomial
- etc.
Author:
Leonardo (leonardo) 2011-12-23
Notes:
--*/
#ifndef _EXPR2VAR_H_
#define _EXPR2VAR_H_
#include"ast.h"
#include"obj_hashtable.h"
/**
\brief The mapping between Z3 expressions and (low level) variables.
*/
class expr2var {
public:
typedef unsigned var;
typedef obj_map<expr, var> expr2var_mapping;
typedef expr2var_mapping::iterator iterator;
typedef ptr_vector<expr>::const_iterator recent_iterator;
protected:
ast_manager & m_manager;
expr2var_mapping m_mapping;
ptr_vector<expr> m_recent_exprs;
bool m_interpreted_vars;
public:
expr2var(ast_manager & m);
~expr2var();
ast_manager & m() const { return m_manager; }
void insert(expr * n, var v);
var to_var(expr * n) const;
bool is_var(expr * n) const { return m_mapping.contains(n); }
void display(std::ostream & out) const;
void mk_inv(expr_ref_vector & var2expr) const;
// return true if the mapping contains interpreted vars.
bool interpreted_vars() const { return m_interpreted_vars; }
iterator begin() const { return m_mapping.begin(); }
iterator end() const { return m_mapping.end(); }
void reset_recent() { m_recent_exprs.reset(); }
// Iterators for traversing the recently registered expressions.
// The set of recent registered expressions is reset by using reset_recent().
recent_iterator begin_recent() const { return m_recent_exprs.begin(); }
recent_iterator end_recent() const { return m_recent_exprs.end(); }
void reset();
};
#endif

97
src/ast/expr_abstract.cpp Normal file
View file

@ -0,0 +1,97 @@
/*++
Copyright (c) 2007 Microsoft Corporation
Module Name:
expr_abstract.h
Abstract:
Abstract occurrences of constants to bound variables.
Author:
Nikolaj Bjorner (nbjorner) 2008-03-08
Notes:
--*/
#include "expr_abstract.h"
#include "map.h"
void expr_abstract(ast_manager& m, unsigned base, unsigned num_bound, expr* const* bound, expr* n, expr_ref& result) {
ast_ref_vector pinned(m);
ptr_vector<expr> stack;
obj_map<expr, expr*> map;
expr * curr = 0, *b = 0;
SASSERT(n->get_ref_count() > 0);
stack.push_back(n);
for (unsigned i = 0; i < num_bound; ++i) {
b = bound[i];
expr* v = m.mk_var(base + num_bound - i - 1, m.get_sort(b));
pinned.push_back(v);
map.insert(b, v);
}
while(!stack.empty()) {
curr = stack.back();
if (map.contains(curr)) {
stack.pop_back();
continue;
}
switch(curr->get_kind()) {
case AST_VAR: {
map.insert(curr, curr);
stack.pop_back();
break;
}
case AST_APP: {
app* a = to_app(curr);
bool all_visited = true;
ptr_vector<expr> args;
for (unsigned i = 0; i < a->get_num_args(); ++i) {
if (!map.find(a->get_arg(i), b)) {
stack.push_back(a->get_arg(i));
all_visited = false;
}
else {
args.push_back(b);
}
}
if (all_visited) {
b = m.mk_app(a->get_decl(), args.size(), args.c_ptr());
pinned.push_back(b);
map.insert(curr, b);
stack.pop_back();
}
break;
}
case AST_QUANTIFIER: {
quantifier* q = to_quantifier(curr);
expr_ref_buffer patterns(m);
expr_ref result1(m);
unsigned new_base = base + q->get_num_decls();
for (unsigned i = 0; i < q->get_num_patterns(); ++i) {
expr_abstract(m, new_base, num_bound, bound, q->get_pattern(i), result1);
patterns.push_back(result1.get());
}
expr_abstract(m, new_base, num_bound, bound, q->get_expr(), result1);
b = m.update_quantifier(q, patterns.size(), patterns.c_ptr(), result1.get());
pinned.push_back(b);
map.insert(curr, b);
stack.pop_back();
break;
}
default:
UNREACHABLE();
}
}
if (!map.find(n, b)) {
UNREACHABLE();
}
result = b;
}

28
src/ast/expr_abstract.h Normal file
View file

@ -0,0 +1,28 @@
/*++
Copyright (c) 2007 Microsoft Corporation
Module Name:
expr_abstract.h
Abstract:
Abstract occurrences of constants to bound variables.
Author:
Nikolaj Bjorner (nbjorner) 2008-03-08
Notes:
--*/
#ifndef _EXPR_ABSTRACT_H_
#define _EXPR_ABSTRACT_H_
#include"ast.h"
void expr_abstract(ast_manager& m, unsigned base, unsigned num_bound, expr* const* bound, expr* n, expr_ref& result);
#endif

142
src/ast/expr_functors.cpp Normal file
View file

@ -0,0 +1,142 @@
/*++
Copyright (c) 2010 Microsoft Corporation
Module Name:
expr_functors.cpp
Abstract:
Functors on expressions.
Author:
Nikolaj Bjorner (nbjorner) 2010-02-19
Revision History:
Hoisted from quant_elim.
--*/
#include "expr_functors.h"
// ----------
// check_pred
bool check_pred::operator()(expr* e) {
if (!m_visited.is_marked(e)) {
m_refs.push_back(e);
visit(e);
}
SASSERT(m_visited.is_marked(e));
return m_pred_holds.is_marked(e);
}
void check_pred::visit(expr* e) {
ptr_vector<expr> todo;
todo.push_back(e);
while (!todo.empty()) {
e = todo.back();
if (m_pred(e)) {
m_pred_holds.mark(e, true);
}
if (m_visited.is_marked(e)) {
todo.pop_back();
continue;
}
switch(e->get_kind()) {
case AST_APP: {
app* a = to_app(e);
bool all_visited = true;
unsigned num_args = a->get_num_args();
for (unsigned i = 0; i < num_args; ++i) {
expr* arg = a->get_arg(i);
if (!m_visited.is_marked(arg)) {
todo.push_back(arg);
all_visited = false;
}
else if (m_pred_holds.is_marked(arg)) {
m_pred_holds.mark(e, true);
}
}
if (all_visited) {
m_visited.mark(e, true);
todo.pop_back();
}
break;
}
case AST_QUANTIFIER: {
quantifier* q = to_quantifier(e);
expr* arg = q->get_expr();
if (m_visited.is_marked(arg)) {
todo.pop_back();
if (m_pred_holds.is_marked(arg)) {
m_pred_holds.mark(e, true);
}
m_visited.mark(e, true);
}
else {
todo.push_back(arg);
}
break;
}
case AST_VAR:
todo.pop_back();
m_visited.mark(e, true);
break;
default:
UNREACHABLE();
break;
}
}
}
// ------------
// contains_app
bool contains_app::operator()(unsigned size, expr* const* es) {
for (unsigned i = 0; i < size; ++i) {
if ((*this)(es[i])) {
return true;
}
}
return false;
}
// -----------
// map_proc
void map_proc::reconstruct(app* a) {
m_args.reset();
bool is_new = false;
for (unsigned i = 0; i < a->get_num_args(); ++i) {
expr* e1 = a->get_arg(i);
expr* e2 = get_expr(e1);
m_args.push_back(e2);
if (e1 != e2) {
is_new = true;
}
}
if (is_new) {
expr* b = m.mk_app(a->get_decl(), m_args.size(), m_args.c_ptr());
m_map.insert(a, b, 0);
}
else {
m_map.insert(a, a, 0);
}
}
void map_proc::visit(quantifier* e) {
expr_ref q(m);
q = m.update_quantifier(e, get_expr(e->get_expr()));
m_map.insert(e, q, 0);
}
expr* map_proc::get_expr(expr* e) {
expr* result = 0;
proof* p = 0;
m_map.get(e, result, p);
return result;
}

121
src/ast/expr_functors.h Normal file
View file

@ -0,0 +1,121 @@
/*++
Copyright (c) 2010 Microsoft Corporation
Module Name:
expr_functors.h
Abstract:
Functors on expressions.
Author:
Nikolaj Bjorner (nbjorner) 2010-02-19
Revision History:
Hoisted from quant_elim.
--*/
#ifndef __EXPR_FUNCTORS_H__
#define __EXPR_FUNCTORS_H__
#include "ast.h"
#include "expr_map.h"
class i_expr_pred {
public:
virtual bool operator()(expr* e) = 0;
virtual ~i_expr_pred() {}
};
/**
\brief Memoizing predicate functor on sub-expressions.
The class is initialized with a predicate 'p' on expressions.
The class is memoizing.
*/
class check_pred {
i_expr_pred& m_pred;
ast_mark m_pred_holds;
ast_mark m_visited;
expr_ref_vector m_refs;
public:
check_pred(i_expr_pred& p, ast_manager& m) : m_pred(p), m_refs(m) {}
bool operator()(expr* e);
void reset() { m_pred_holds.reset(); m_visited.reset(); m_refs.reset(); }
private:
void visit(expr* e);
};
/**
\brief Determine if expression 'e' or vector of expressions 'v' contains the app x
*/
class contains_app {
class pred : public i_expr_pred {
app* m_x;
public:
pred(app* x) : m_x(x) {}
virtual bool operator()(expr* e) {
return m_x == e;
}
};
app_ref m_x;
pred m_pred;
check_pred m_check;
public:
contains_app(ast_manager& m, app* x) :
m_x(x, m), m_pred(x), m_check(m_pred, m) {}
bool operator()(expr* e) {
return m_check(e);
}
bool operator()(expr_ref_vector const& v) {
return (*this)(v.size(), v.c_ptr());
}
bool operator()(unsigned size, expr* const* es);
app* x() const { return m_x; }
};
/**
\brief Base class of functor that applies map to expressions.
*/
class map_proc {
protected:
ast_manager& m;
expr_map m_map;
ptr_vector<expr> m_args;
public:
map_proc(ast_manager& m):
m(m),
m_map(m)
{}
void reset() { m_map.reset(); }
void visit(var* e) { m_map.insert(e, e, 0); }
void visit(quantifier* e);
void reconstruct(app* a);
expr* get_expr(expr* e);
};
#endif

88
src/ast/expr_stat.cpp Normal file
View file

@ -0,0 +1,88 @@
/*++
Copyright (c) 2006 Microsoft Corporation
Module Name:
expr_stat.cpp
Abstract:
Expression statistics (symbol count, var count, depth, ...)
All functions in these module assume expressions do not contain
nested quantifiers.
Author:
Leonardo de Moura (leonardo) 2008-02-05.
Revision History:
--*/
#include"for_each_expr.h"
#include"expr_stat.h"
void get_expr_stat(expr * n, expr_stat & r) {
typedef std::pair<expr *, unsigned> pair;
buffer<pair> todo;
todo.push_back(pair(n, 0));
while (!todo.empty()) {
pair & p = todo.back();
n = p.first;
unsigned depth = p.second;
unsigned j;
todo.pop_back();
r.m_sym_count++;
if (depth > r.m_depth)
r.m_depth = depth;
switch (n->get_kind()) {
case AST_APP:
j = to_app(n)->get_num_args();
if (j == 0)
r.m_const_count++;
while (j > 0) {
--j;
todo.push_back(pair(to_app(n)->get_arg(j), depth + 1));
}
break;
case AST_VAR:
if (to_var(n)->get_idx() > r.m_max_var_idx)
r.m_max_var_idx = to_var(n)->get_idx();
r.m_ground = false;
break;
case AST_QUANTIFIER:
todo.push_back(pair(to_quantifier(n)->get_expr(), depth+1));
break;
default:
UNREACHABLE();
}
}
}
unsigned get_symbol_count(expr * n) {
unsigned r = 0;
ptr_buffer<expr> todo;
todo.push_back(n);
while (!todo.empty()) {
n = todo.back();
unsigned j;
todo.pop_back();
r++;
switch (n->get_kind()) {
case AST_APP:
j = to_app(n)->get_num_args();
while (j > 0) {
--j;
todo.push_back(to_app(n)->get_arg(j));
}
break;
case AST_QUANTIFIER:
todo.push_back(to_quantifier(n)->get_expr());
break;
default:
break;
}
}
return r;
}

50
src/ast/expr_stat.h Normal file
View file

@ -0,0 +1,50 @@
/*++
Copyright (c) 2006 Microsoft Corporation
Module Name:
expr_stat.h
Abstract:
Expression statistics (symbol count, var count, depth, ...)
All functions in these module assume expressions do not contain
nested quantifiers.
Author:
Leonardo de Moura (leonardo) 2008-02-05.
Revision History:
--*/
#ifndef _EXPR_STAT_H_
#define _EXPR_STAT_H_
class expr;
struct expr_stat {
unsigned m_sym_count; // symbol count
unsigned m_depth; // depth
unsigned m_const_count; // constant count
unsigned m_max_var_idx;
bool m_ground;
expr_stat():m_sym_count(0), m_depth(0), m_const_count(0), m_max_var_idx(0), m_ground(true) {}
};
/**
\brief Collect statistics regarding the given expression.
\warning This function traverses the dag as a tree.
*/
void get_expr_stat(expr * n, expr_stat & r);
/**
\brief Return the number of symbols in \c n.
\warning This function traverses the dag as a tree.
*/
unsigned get_symbol_count(expr * n);
#endif /* _EXPR_STAT_H_ */

604
src/ast/static_features.cpp Normal file
View file

@ -0,0 +1,604 @@
/*++
Copyright (c) 2006 Microsoft Corporation
Module Name:
static_features.cpp
Abstract:
<abstract>
Author:
Leonardo de Moura (leonardo) 2008-05-16.
Revision History:
--*/
#include"static_features.h"
#include"ast_pp.h"
static_features::static_features(ast_manager & m):
m_manager(m),
m_autil(m),
m_bfid(m.get_basic_family_id()),
m_afid(m.get_family_id("arith")),
m_lfid(m.get_family_id("label")),
m_label_sym("label"),
m_pattern_sym("pattern"),
m_expr_list_sym("expr-list") {
reset();
}
void static_features::reset() {
m_already_visited .reset();
m_cnf = true;
m_num_exprs = 0;
m_num_roots = 0;
m_max_depth = 0;
m_num_quantifiers = 0;
m_num_quantifiers_with_patterns = 0;
m_num_quantifiers_with_multi_patterns = 0;
m_num_clauses = 0;
m_num_bin_clauses = 0;
m_num_units = 0;
m_sum_clause_size = 0;
m_num_nested_formulas = 0;
m_num_bool_exprs = 0;
m_num_bool_constants = 0;
m_num_formula_trees = 0;
m_max_formula_depth = 0;
m_sum_formula_depth = 0;
m_num_or_and_trees = 0;
m_max_or_and_tree_depth = 0;
m_sum_or_and_tree_depth = 0;
m_num_ite_trees = 0;
m_max_ite_tree_depth = 0;
m_sum_ite_tree_depth = 0;
m_num_ors = 0;
m_num_ands = 0;
m_num_iffs = 0;
m_num_ite_formulas = 0;
m_num_ite_terms = 0;
m_num_sharing = 0;
m_num_interpreted_exprs = 0;
m_num_uninterpreted_exprs = 0;
m_num_interpreted_constants = 0;
m_num_uninterpreted_constants = 0;
m_num_uninterpreted_functions = 0;
m_num_eqs = 0;
m_has_rational = false;
m_has_int = false;
m_has_real = false;
m_arith_k_sum .reset();
m_num_arith_terms = 0;
m_num_arith_eqs = 0;
m_num_arith_ineqs = 0;
m_num_diff_terms = 0;
m_num_diff_eqs = 0;
m_num_diff_ineqs = 0;
m_num_simple_eqs = 0;
m_num_simple_ineqs = 0;
m_num_non_linear = 0;
m_num_apps .reset();
m_num_theory_terms .reset();
m_num_theory_atoms .reset();
m_num_theory_constants .reset();
m_num_theory_eqs .reset();
m_num_aliens = 0;
m_num_aliens_per_family .reset();
m_num_theories = 0;
m_theories .reset();
m_max_stack_depth = 500;
flush_cache();
}
void static_features::flush_cache() {
m_expr2depth.reset();
m_expr2or_and_depth.reset();
m_expr2ite_depth.reset();
m_expr2formula_depth.reset();
}
#if 0
bool static_features::is_non_linear(expr * e) const {
if (!is_arith_expr(e))
return false;
if (is_numeral(e))
return true;
if (m_autil.is_add(e))
return true; // the non
}
#endif
bool static_features::is_diff_term(expr const * e, rational & r) const {
// lhs can be 'x' or '(+ k x)'
if (!is_arith_expr(e)) {
r.reset();
return true;
}
if (is_numeral(e, r))
return true;
return m_autil.is_add(e) && to_app(e)->get_num_args() == 2 && is_numeral(to_app(e)->get_arg(0), r) && !is_arith_expr(to_app(e)->get_arg(1));
}
bool static_features::is_diff_atom(expr const * e) const {
if (!is_bool(e))
return false;
if (!m_manager.is_eq(e) && !is_arith_expr(e))
return false;
SASSERT(to_app(e)->get_num_args() == 2);
expr * lhs = to_app(e)->get_arg(0);
expr * rhs = to_app(e)->get_arg(1);
if (!is_arith_expr(lhs) && !is_arith_expr(rhs))
return true;
if (!is_numeral(rhs))
return false;
// lhs can be 'x' or '(+ x (* -1 y))'
if (!is_arith_expr(lhs))
return true;
expr* arg1, *arg2;
if (!m_autil.is_add(lhs, arg1, arg2))
return false;
// x
if (is_arith_expr(arg1))
return false;
// arg2: (* -1 y)
expr* m1, *m2;
return m_autil.is_mul(arg2, m1, m2) && is_minus_one(m1) && !is_arith_expr(m2);
}
bool static_features::is_gate(expr const * e) const {
if (is_basic_expr(e)) {
switch (to_app(e)->get_decl_kind()) {
case OP_ITE: case OP_AND: case OP_OR: case OP_IFF: case OP_XOR: case OP_IMPLIES:
return true;
}
}
return false;
}
void static_features::update_core(expr * e) {
m_num_exprs++;
// even if a benchmark does not contain any theory interpreted function decls, we still have to install
// the theory if the benchmark contains constants or function applications of an interpreted sort.
sort * s = m_manager.get_sort(e);
mark_theory(s->get_family_id());
bool _is_gate = is_gate(e);
bool _is_eq = m_manager.is_eq(e);
if (_is_gate) {
m_cnf = false;
m_num_nested_formulas++;
switch (to_app(e)->get_decl_kind()) {
case OP_ITE:
if (is_bool(e))
m_num_ite_formulas++;
else {
m_num_ite_terms++;
// process then&else nodes
for (unsigned i = 1; i < 3; i++) {
expr * arg = to_app(e)->get_arg(i);
acc_num(arg);
// Must check whether arg is diff logic or not.
// Otherwise, problem can be incorrectly tagged as diff logic.
sort * arg_s = m_manager.get_sort(arg);
family_id fid_arg = arg_s->get_family_id();
if (fid_arg == m_afid) {
m_num_arith_terms++;
rational k;
TRACE("diff_term", tout << "diff_term: " << is_diff_term(arg, k) << "\n" << mk_pp(arg, m_manager) << "\n";);
if (is_diff_term(arg, k)) {
m_num_diff_terms++;
acc_num(k);
}
}
}
}
break;
case OP_AND:
m_num_ands++;
break;
case OP_OR:
m_num_ors++;
break;
case OP_IFF:
m_num_iffs++;
break;
}
}
if (is_bool(e)) {
m_num_bool_exprs++;
if (is_app(e) && to_app(e)->get_num_args() == 0)
m_num_bool_constants++;
}
if (is_quantifier(e)) {
m_num_quantifiers++;
unsigned num_patterns = to_quantifier(e)->get_num_patterns();
if (num_patterns > 0) {
m_num_quantifiers_with_patterns++;
for (unsigned i = 0; i < num_patterns; i++) {
expr * p = to_quantifier(e)->get_pattern(i);
if (is_app(p) && to_app(p)->get_num_args() > 1) {
m_num_quantifiers_with_multi_patterns++;
break;
}
}
}
}
bool _is_le_ge = m_autil.is_le(e) || m_autil.is_ge(e);
if (_is_le_ge) {
m_num_arith_ineqs++;
TRACE("diff_atom", tout << "diff_atom: " << is_diff_atom(e) << "\n" << mk_pp(e, m_manager) << "\n";);
if (is_diff_atom(e))
m_num_diff_ineqs++;
if (!is_arith_expr(to_app(e)->get_arg(0)))
m_num_simple_ineqs++;
acc_num(to_app(e)->get_arg(1));
}
rational r;
if (is_numeral(e, r)) {
if (!r.is_int())
m_has_rational = true;
}
if (_is_eq) {
m_num_eqs++;
if (is_numeral(to_app(e)->get_arg(1))) {
acc_num(to_app(e)->get_arg(1));
m_num_arith_eqs++;
TRACE("diff_atom", tout << "diff_atom: " << is_diff_atom(e) << "\n" << mk_pp(e, m_manager) << "\n";);
if (is_diff_atom(e))
m_num_diff_eqs++;
if (!is_arith_expr(to_app(e)->get_arg(0)))
m_num_simple_eqs++;
}
sort * s = m_manager.get_sort(to_app(e)->get_arg(0));
family_id fid = s->get_family_id();
if (fid != null_family_id && fid != m_bfid)
inc_theory_eqs(fid);
}
if (!m_has_int && m_autil.is_int(e))
m_has_int = true;
if (!m_has_real && m_autil.is_real(e))
m_has_real = true;
if (is_app(e)) {
family_id fid = to_app(e)->get_family_id();
mark_theory(fid);
if (fid != null_family_id && fid != m_bfid) {
m_num_interpreted_exprs++;
if (is_bool(e))
inc_theory_atoms(fid);
else
inc_theory_terms(fid);
if (to_app(e)->get_num_args() == 0)
m_num_interpreted_constants++;
}
if (fid == m_afid) {
switch (to_app(e)->get_decl_kind()) {
case OP_MUL:
if (!is_numeral(to_app(e)->get_arg(0)))
m_num_non_linear++;
break;
case OP_DIV:
case OP_IDIV:
case OP_REM:
case OP_MOD:
if (!is_numeral(to_app(e)->get_arg(1)))
m_num_non_linear++;
break;
}
}
if (fid == null_family_id) {
m_num_uninterpreted_exprs++;
if (to_app(e)->get_num_args() == 0) {
m_num_uninterpreted_constants++;
sort * s = m_manager.get_sort(e);
family_id fid = s->get_family_id();
if (fid != null_family_id && fid != m_bfid)
inc_theory_constants(fid);
}
}
func_decl * d = to_app(e)->get_decl();
inc_num_apps(d);
if (d->get_arity() > 0 && !is_marked(d)) {
mark(d);
if (fid == null_family_id)
m_num_uninterpreted_functions++;
}
if (!_is_eq && !_is_gate) {
unsigned num_args = to_app(e)->get_num_args();
for (unsigned i = 0; i < num_args; i++) {
expr * arg = to_app(e)->get_arg(i);
sort * arg_s = m_manager.get_sort(arg);
family_id fid_arg = arg_s->get_family_id();
if (fid_arg != fid && fid_arg != null_family_id) {
m_num_aliens++;
inc_num_aliens(fid_arg);
if (fid_arg == m_afid) {
SASSERT(!_is_le_ge);
m_num_arith_terms++;
rational k;
TRACE("diff_term", tout << "diff_term: " << is_diff_term(arg, k) << "\n" << mk_pp(arg, m_manager) << "\n";);
if (is_diff_term(arg, k)) {
m_num_diff_terms++;
acc_num(k);
}
}
}
}
}
}
}
void static_features::process(expr * e, bool form_ctx, bool or_and_ctx, bool ite_ctx, unsigned stack_depth) {
TRACE("static_features", tout << "processing\n" << mk_pp(e, m_manager) << "\n";);
if (is_var(e))
return;
if (is_marked(e)) {
m_num_sharing++;
return;
}
if (stack_depth > m_max_stack_depth) {
return;
}
mark(e);
update_core(e);
if (is_quantifier(e)) {
expr * body = to_quantifier(e)->get_expr();
process(body, false, false, false, stack_depth+1);
set_depth(e, get_depth(body)+1);
return;
}
bool form_ctx_new = false;
bool or_and_ctx_new = false;
bool ite_ctx_new = false;
if (is_basic_expr(e)) {
switch (to_app(e)->get_decl_kind()) {
case OP_ITE:
form_ctx_new = m_manager.is_bool(e);
ite_ctx_new = true;
break;
case OP_AND:
case OP_OR:
form_ctx_new = true;
or_and_ctx_new = true;
break;
case OP_IFF:
form_ctx_new = true;
break;
}
}
unsigned depth = 0;
unsigned form_depth = 0;
unsigned or_and_depth = 0;
unsigned ite_depth = 0;
unsigned num_args = to_app(e)->get_num_args();
for (unsigned i = 0; i < num_args; i++) {
expr * arg = to_app(e)->get_arg(i);
if (m_manager.is_not(arg))
arg = to_app(arg)->get_arg(0);
process(arg, form_ctx_new, or_and_ctx_new, ite_ctx_new, stack_depth+1);
depth = std::max(depth, get_depth(arg));
if (form_ctx_new)
form_depth = std::max(form_depth, get_form_depth(arg));
if (or_and_ctx_new)
or_and_depth = std::max(or_and_depth, get_or_and_depth(arg));
if (ite_ctx_new)
ite_depth = std::max(ite_depth, get_ite_depth(arg));
}
depth++;
set_depth(e, depth);
if (depth > m_max_depth)
m_max_depth = depth;
if (form_ctx_new) {
form_depth++;
if (!form_ctx) {
m_num_formula_trees++;
m_sum_formula_depth += form_depth;
if (form_depth > m_max_formula_depth)
m_max_formula_depth = form_depth;
}
set_form_depth(e, form_depth);
}
if (or_and_ctx_new) {
or_and_depth++;
if (!or_and_ctx) {
m_num_or_and_trees++;
m_sum_or_and_tree_depth += or_and_depth;
if (or_and_depth > m_max_or_and_tree_depth)
m_max_or_and_tree_depth = or_and_depth;
}
set_or_and_depth(e, or_and_depth);
}
if (ite_ctx_new) {
ite_depth++;
if (!ite_ctx) {
m_num_ite_trees++;
m_sum_ite_tree_depth += ite_depth;
if (ite_depth >= m_max_ite_tree_depth)
m_max_ite_tree_depth = ite_depth;
}
set_ite_depth(e, ite_depth);
}
}
void static_features::process_root(expr * e) {
if (is_marked(e)) {
m_num_sharing++;
return;
}
m_num_roots++;
if (m_manager.is_or(e)) {
mark(e);
m_num_clauses++;
m_num_bool_exprs++;
unsigned num_args = to_app(e)->get_num_args();
m_sum_clause_size += num_args;
if (num_args == 2)
m_num_bin_clauses++;
unsigned depth = 0;
unsigned form_depth = 0;
unsigned or_and_depth = 0;
for (unsigned i = 0; i < num_args; i++) {
expr * arg = to_app(e)->get_arg(i);
if (m_manager.is_not(arg))
arg = to_app(arg)->get_arg(0);
process(arg, true, true, false, 0);
depth = std::max(depth, get_depth(arg));
form_depth = std::max(form_depth, get_form_depth(arg));
or_and_depth = std::max(or_and_depth, get_or_and_depth(arg));
}
depth++;
set_depth(e, depth);
if (depth > m_max_depth)
m_max_depth = depth;
form_depth++;
m_num_formula_trees++;
m_sum_formula_depth += form_depth;
if (form_depth > m_max_formula_depth)
m_max_formula_depth = form_depth;
set_form_depth(e, form_depth);
or_and_depth++;
m_num_or_and_trees++;
m_sum_or_and_tree_depth += or_and_depth;
if (or_and_depth > m_max_or_and_tree_depth)
m_max_or_and_tree_depth = or_and_depth;
set_or_and_depth(e, or_and_depth);
return;
}
if (!is_gate(e)) {
m_sum_clause_size++;
m_num_units++;
m_num_clauses++;
}
process(e, false, false, false, 0);
}
void static_features::collect(unsigned num_formulas, expr * const * formulas) {
for (unsigned i = 0; i < num_formulas; i++)
process_root(formulas[i]);
}
bool static_features::internal_family(symbol const & f_name) const {
return f_name == m_label_sym || f_name == m_pattern_sym || f_name == m_expr_list_sym;
}
void static_features::display_family_data(std::ostream & out, char const * prefix, unsigned_vector const & data) const {
for (unsigned fid = 0; fid < data.size(); fid++) {
symbol const & n = m_manager.get_family_name(fid);
if (!internal_family(n))
out << prefix << "_" << n << " " << data[fid] << "\n";
}
}
bool static_features::has_uf() const {
return m_num_uninterpreted_functions > 0;
}
unsigned static_features::num_non_uf_theories() const {
return m_num_theories;
}
unsigned static_features::num_theories() const {
return (num_non_uf_theories() + (has_uf() ? 1 : 0));
}
void static_features::display_primitive(std::ostream & out) const {
out << "BEGIN_PRIMITIVE_STATIC_FEATURES" << "\n";
out << "CNF " << m_cnf << "\n";
out << "NUM_EXPRS " << m_num_exprs << "\n";
out << "NUM_ROOTS " << m_num_roots << "\n";
out << "MAX_DEPTH " << m_max_depth << "\n";
out << "NUM_QUANTIFIERS " << m_num_quantifiers << "\n";
out << "NUM_QUANTIFIERS_WITH_PATTERNS " << m_num_quantifiers_with_patterns << "\n";
out << "NUM_QUANTIFIERS_WITH_MULTI_PATTERNS " << m_num_quantifiers_with_multi_patterns << "\n";
out << "NUM_CLAUSES " << m_num_clauses << "\n";
out << "NUM_BIN_CLAUSES " << m_num_bin_clauses << "\n";
out << "NUM_UNITS " << m_num_units << "\n";
out << "SUM_CLAUSE_SIZE " << m_sum_clause_size << "\n";
out << "NUM_NESTED_FORMULAS " << m_num_nested_formulas << "\n";
out << "NUM_BOOL_EXPRS " << m_num_bool_exprs << "\n";
out << "NUM_BOOL_CONSTANTS " << m_num_bool_constants << "\n";
out << "NUM_FORMULA_TREES " << m_num_formula_trees << "\n";
out << "MAX_FORMULA_DEPTH " << m_max_formula_depth << "\n";
out << "SUM_FORMULA_DEPTH " << m_sum_formula_depth << "\n";
out << "NUM_OR_AND_TREES " << m_num_or_and_trees << "\n";
out << "MAX_OR_AND_TREE_DEPTH " << m_max_or_and_tree_depth << "\n";
out << "SUM_OR_AND_TREE_DEPTH " << m_sum_or_and_tree_depth << "\n";
out << "NUM_ITE_TREES " << m_num_ite_trees << "\n";
out << "MAX_ITE_TREE_DEPTH " << m_max_ite_tree_depth << "\n";
out << "SUM_ITE_TREE_DEPTH " << m_sum_ite_tree_depth << "\n";
out << "NUM_ORS " << m_num_ors << "\n";
out << "NUM_ANDS " << m_num_ands << "\n";
out << "NUM_IFFS " << m_num_iffs << "\n";
out << "NUM_ITE_FORMULAS " << m_num_ite_formulas << "\n";
out << "NUM_ITE_TERMS " << m_num_ite_terms << "\n";
out << "NUM_SHARING " << m_num_sharing << "\n";
out << "NUM_INTERPRETED_EXPRS " << m_num_interpreted_exprs << "\n";
out << "NUM_UNINTERPRETED_EXPRS " << m_num_uninterpreted_exprs << "\n";
out << "NUM_INTERPRETED_CONSTANTS " << m_num_interpreted_constants << "\n";
out << "NUM_UNINTERPRETED_CONSTANTS " << m_num_uninterpreted_constants << "\n";
out << "NUM_UNINTERPRETED_FUNCTIONS " << m_num_uninterpreted_functions << "\n";
out << "NUM_EQS " << m_num_eqs << "\n";
out << "HAS_RATIONAL " << m_has_rational << "\n";
out << "HAS_INT " << m_has_int << "\n";
out << "HAS_REAL " << m_has_real << "\n";
out << "ARITH_K_SUM " << m_arith_k_sum << "\n";
out << "NUM_ARITH_TERMS " << m_num_arith_terms << "\n";
out << "NUM_ARITH_EQS " << m_num_arith_eqs << "\n";
out << "NUM_ARITH_INEQS " << m_num_arith_ineqs << "\n";
out << "NUM_DIFF_TERMS " << m_num_diff_terms << "\n";
out << "NUM_DIFF_EQS " << m_num_diff_eqs << "\n";
out << "NUM_DIFF_INEQS " << m_num_diff_ineqs << "\n";
out << "NUM_SIMPLE_EQS " << m_num_simple_eqs << "\n";
out << "NUM_SIMPLE_INEQS " << m_num_simple_ineqs << "\n";
out << "NUM_NON_LINEAR " << m_num_non_linear << "\n";
out << "NUM_ALIENS " << m_num_aliens << "\n";
display_family_data(out, "NUM_TERMS", m_num_theory_terms);
display_family_data(out, "NUM_ATOMS", m_num_theory_atoms);
display_family_data(out, "NUM_CONSTANTS", m_num_theory_constants);
display_family_data(out, "NUM_EQS", m_num_theory_eqs);
display_family_data(out, "NUM_ALIENS", m_num_aliens_per_family);
out << "NUM_THEORIES " << num_theories() << "\n";
out << "END_PRIMITIVE_STATIC_FEATURES" << "\n";
}
void static_features::display(std::ostream & out) const {
out << "BEGIN_STATIC_FEATURES" << "\n";
out << "CNF " << m_cnf << "\n";
out << "MAX_DEPTH " << m_max_depth << "\n";
out << "MAX_OR_AND_TREE_DEPTH " << m_max_or_and_tree_depth << "\n";
out << "MAX_ITE_TREE_DEPTH " << m_max_ite_tree_depth << "\n";
out << "HAS_INT " << m_has_int << "\n";
out << "HAS_REAL " << m_has_real << "\n";
out << "HAS_QUANTIFIERS " << (m_num_quantifiers > 0) << "\n";
out << "PERC_QUANTIFIERS_WITH_PATTERNS " << (m_num_quantifiers > 0 ? (double) m_num_quantifiers_with_patterns / (double) m_num_quantifiers : 0) << "\n";
out << "PERC_QUANTIFIERS_WITH_MULTI_PATTERNS " << (m_num_quantifiers > 0 ? (double) m_num_quantifiers_with_multi_patterns / (double) m_num_quantifiers : 0) << "\n";
out << "IS_NON_LINEAR " << (m_num_non_linear > 0) << "\n";
out << "THEORY_COMBINATION " << (num_theories() > 1) << "\n";
out << "AVG_CLAUSE_SIZE " << (m_num_clauses > 0 ? (double) m_sum_clause_size / (double) m_num_clauses : 0) << "\n";
out << "PERC_BOOL_CONSTANTS " << (m_num_uninterpreted_constants > 0 ? (double) m_num_bool_constants / (double) m_num_uninterpreted_constants : 0) << "\n";
out << "PERC_NESTED_FORMULAS " << (m_num_bool_exprs > 0 ? (double) m_num_nested_formulas / (double) m_num_bool_exprs : 0) << "\n";
out << "IS_DIFF " << (m_num_arith_eqs == m_num_diff_eqs && m_num_arith_ineqs == m_num_diff_ineqs && m_num_arith_terms == m_num_diff_terms) << "\n";
out << "INEQ_EQ_RATIO " << (m_num_arith_eqs > 0 ? (double) m_num_arith_ineqs / (double) m_num_arith_eqs : 0) << "\n";
out << "PERC_ARITH_EQS " << (m_num_eqs > 0 ? (double) m_num_arith_eqs / (double) m_num_eqs : 0) << "\n";
out << "PERC_DIFF_EQS " << (m_num_arith_eqs > 0 ? (double) m_num_diff_eqs / (double) m_num_arith_eqs : 0) << "\n";
out << "PERC_DIFF_INEQS " << (m_num_arith_ineqs > 0 ? (double) m_num_diff_ineqs / (double) m_num_arith_ineqs : 0) << "\n";
out << "PERC_SIMPLE_EQS " << (m_num_arith_eqs > 0 ? (double) m_num_simple_eqs / (double) m_num_arith_eqs : 0) << "\n";
out << "PERC_SIMPLE_INEQS " << (m_num_arith_ineqs > 0 ? (double) m_num_simple_ineqs / (double) m_num_arith_ineqs : 0) << "\n";
out << "PERC_ALIENS " << (m_num_exprs > 0 ? (double) m_num_aliens / (double) m_num_exprs : 0) << "\n";
out << "END_STATIC_FEATURES" << "\n";
}
void static_features::get_feature_vector(vector<double> & result) {
}

169
src/ast/static_features.h Normal file
View file

@ -0,0 +1,169 @@
/*++
Copyright (c) 2006 Microsoft Corporation
Module Name:
static_features.h
Abstract:
<abstract>
Author:
Leonardo de Moura (leonardo) 2008-05-16.
Revision History:
--*/
#ifndef _STATIC_FEATURES_H_
#define _STATIC_FEATURES_H_
#include"ast.h"
#include"arith_decl_plugin.h"
#include"map.h"
struct static_features {
ast_manager & m_manager;
arith_util m_autil;
family_id m_bfid;
family_id m_afid;
family_id m_lfid;
ast_mark m_already_visited;
bool m_cnf;
unsigned m_num_exprs; //
unsigned m_num_roots; //
unsigned m_max_depth;
unsigned m_num_quantifiers; //
unsigned m_num_quantifiers_with_patterns; //
unsigned m_num_quantifiers_with_multi_patterns; //
unsigned m_num_clauses;
unsigned m_num_bin_clauses; //
unsigned m_num_units; //
unsigned m_sum_clause_size;
unsigned m_num_nested_formulas; //
unsigned m_num_bool_exprs; //
unsigned m_num_bool_constants; //
unsigned m_num_formula_trees;
unsigned m_max_formula_depth;
unsigned m_sum_formula_depth;
unsigned m_num_or_and_trees;
unsigned m_max_or_and_tree_depth;
unsigned m_sum_or_and_tree_depth;
unsigned m_num_ite_trees;
unsigned m_max_ite_tree_depth;
unsigned m_sum_ite_tree_depth;
unsigned m_num_ands; //
unsigned m_num_ors; // num nested ors
unsigned m_num_iffs; //
unsigned m_num_ite_formulas; //
unsigned m_num_ite_terms; //
unsigned m_num_sharing;
unsigned m_num_interpreted_exprs; // doesn't include bool_exprs
unsigned m_num_uninterpreted_exprs; //
unsigned m_num_interpreted_constants; // doesn't include bool_consts
unsigned m_num_uninterpreted_constants; //
unsigned m_num_uninterpreted_functions; //
unsigned m_num_eqs; //
bool m_has_rational; //
bool m_has_int; //
bool m_has_real; //
rational m_arith_k_sum; // sum of the numerals in arith atoms.
unsigned m_num_arith_terms;
unsigned m_num_arith_eqs; // equalities of the form t = k where k is a numeral
unsigned m_num_arith_ineqs;
unsigned m_num_diff_terms; // <= m_num_arith_terms
unsigned m_num_diff_eqs; // <= m_num_arith_eqs
unsigned m_num_diff_ineqs; // <= m_num_arith_ineqs
unsigned m_num_simple_eqs; // eqs of the form x = k
unsigned m_num_simple_ineqs; // ineqs of the form x <= k or x >= k
unsigned m_num_non_linear;
unsigned_vector m_num_apps; // mapping decl_id -> num_apps;
unsigned_vector m_num_theory_terms; // mapping family_id -> num_terms
unsigned_vector m_num_theory_atoms; // mapping family_id -> num_atoms
unsigned_vector m_num_theory_constants; // mapping family_id -> num_exprs
unsigned_vector m_num_theory_eqs; // mapping family_id -> num_eqs
unsigned m_num_aliens; //
unsigned_vector m_num_aliens_per_family; // mapping family_id -> num_alies exprs
unsigned_vector m_expr2depth; // expr-id -> depth
unsigned m_max_stack_depth; // maximal depth of stack we are willing to walk.
u_map<unsigned> m_expr2or_and_depth;
u_map<unsigned> m_expr2ite_depth;
u_map<unsigned> m_expr2formula_depth;
unsigned m_num_theories;
svector<bool> m_theories; // mapping family_id -> bool
symbol m_label_sym;
symbol m_pattern_sym;
symbol m_expr_list_sym;
bool is_marked(ast * e) const { return m_already_visited.is_marked(e); }
void mark(ast * e) { m_already_visited.mark(e, true); }
bool is_bool(expr const * e) const { return m_manager.is_bool(e); }
bool is_basic_expr(expr const * e) const { return is_app(e) && to_app(e)->get_family_id() == m_bfid; }
bool is_arith_expr(expr const * e) const { return is_app(e) && to_app(e)->get_family_id() == m_afid; }
bool is_numeral(expr const * e) const { return m_autil.is_numeral(e); }
bool is_numeral(expr const * e, rational & r) const { return m_autil.is_numeral(e, r); }
bool is_minus_one(expr const * e) const { rational r; return m_autil.is_numeral(e, r) && r.is_minus_one(); }
bool is_diff_term(expr const * e, rational & r) const;
bool is_diff_atom(expr const * e) const;
bool is_gate(expr const * e) const;
void mark_theory(family_id fid) {
if (fid != null_family_id && !m_manager.is_builtin_family_id(fid) && !m_theories.get(fid, false)) {
m_theories.setx(fid, true, false);
m_num_theories++;
}
}
void acc_num(rational const & r) {
if (r.is_neg())
m_arith_k_sum -= r;
else
m_arith_k_sum += r;
}
void acc_num(expr const * e) {
rational r;
if (is_numeral(e, r)) {
acc_num(r);
}
}
void inc_num_apps(func_decl const * d) { unsigned id = d->get_decl_id(); m_num_apps.reserve(id+1, 0); m_num_apps[id]++; }
void inc_theory_terms(family_id fid) { m_num_theory_terms.reserve(fid+1, 0); m_num_theory_terms[fid]++; }
void inc_theory_atoms(family_id fid) { m_num_theory_atoms.reserve(fid+1, 0); m_num_theory_atoms[fid]++; }
void inc_theory_constants(family_id fid) { m_num_theory_constants.reserve(fid+1, 0); m_num_theory_constants[fid]++; }
void inc_theory_eqs(family_id fid) { m_num_theory_eqs.reserve(fid+1, 0); m_num_theory_eqs[fid]++; }
void inc_num_aliens(family_id fid) { m_num_aliens_per_family.reserve(fid+1, 0); m_num_aliens_per_family[fid]++; }
void update_core(expr * e);
void process(expr * e, bool form_ctx, bool or_and_ctx, bool ite_ctx, unsigned stack_depth);
void process_root(expr * e);
unsigned get_depth(expr const * e) const { return m_expr2depth.get(e->get_id(), 1); }
void set_depth(expr const * e, unsigned d) { m_expr2depth.setx(e->get_id(), d, 1); }
unsigned get_or_and_depth(expr const * e) const { unsigned d = 0; m_expr2or_and_depth.find(e->get_id(), d); return d; }
void set_or_and_depth(expr const * e, unsigned d) { m_expr2or_and_depth.insert(e->get_id(), d); }
unsigned get_ite_depth(expr const * e) const { unsigned d = 0; m_expr2ite_depth.find(e->get_id(), d); return d; }
void set_ite_depth(expr const * e, unsigned d) { m_expr2ite_depth.insert(e->get_id(), d); }
unsigned get_form_depth(expr const * e) const { unsigned d = 0; m_expr2formula_depth.find(e->get_id(), d); return d; }
void set_form_depth(expr const * e, unsigned d) { m_expr2formula_depth.insert(e->get_id(), d); }
static_features(ast_manager & m);
void reset();
void flush_cache();
void collect(unsigned num_formulas, expr * const * formulas);
void collect(expr * f) { process_root(f); }
bool internal_family(symbol const & f_name) const;
void display_family_data(std::ostream & out, char const * prefix, unsigned_vector const & data) const;
void display_primitive(std::ostream & out) const;
void display(std::ostream & out) const;
void get_feature_vector(vector<double> & result);
bool has_uf() const;
unsigned num_theories() const;
unsigned num_non_uf_theories() const;
};
#endif /* _STATIC_FEATURES_H_ */

404
src/ast/trail.h Normal file
View file

@ -0,0 +1,404 @@
/*++
Copyright (c) 2006 Microsoft Corporation
Module Name:
trail.h
Abstract:
<abstract>
Author:
Leonardo de Moura (leonardo) 2008-06-02.
Revision History:
--*/
#ifndef _TRAIL_H_
#define _TRAIL_H_
#include"ast.h"
#include"obj_hashtable.h"
#include"region.h"
template<typename Ctx>
class trail {
public:
virtual ~trail() {
}
virtual void undo(Ctx & ctx) = 0;
};
template<typename Ctx, typename T>
class value_trail : public trail<Ctx> {
T & m_value;
T m_old_value;
public:
value_trail(T & value):
m_value(value),
m_old_value(value) {
}
virtual ~value_trail() {
}
virtual void undo(Ctx & ctx) {
m_value = m_old_value;
}
};
template<typename Ctx>
class reset_flag_trail : public trail<Ctx> {
bool & m_value;
public:
reset_flag_trail(bool & value):
m_value(value) {
}
virtual ~reset_flag_trail() {
}
virtual void undo(Ctx & ctx) {
m_value = false;
}
};
template<typename Ctx, typename T>
class set_ptr_trail : public trail<Ctx> {
T * & m_ptr;
public:
set_ptr_trail(T * & ptr):
m_ptr(ptr) {
SASSERT(m_ptr == 0);
}
virtual void undo(Ctx & ctx) {
m_ptr = 0;
}
};
template<typename Ctx, typename T, bool CallDestructors=true>
class restore_size_trail : public trail<Ctx> {
vector<T, CallDestructors> & m_vector;
unsigned m_old_size;
public:
restore_size_trail(vector<T, CallDestructors> & v, unsigned sz):
m_vector(v),
m_old_size(sz) {
}
restore_size_trail(vector<T, CallDestructors> & v):
m_vector(v),
m_old_size(v.size()) {
}
virtual ~restore_size_trail() {
}
virtual void undo(Ctx & ctx) {
m_vector.shrink(m_old_size);
}
};
template<typename Ctx, typename T, bool CallDestructors=true>
class vector_value_trail : public trail<Ctx> {
vector<T, CallDestructors> & m_vector;
unsigned m_idx;
T m_old_value;
public:
vector_value_trail(vector<T, CallDestructors> & v, unsigned idx):
m_vector(v),
m_idx(idx),
m_old_value(v[idx]) {
}
virtual ~vector_value_trail() {
}
virtual void undo(Ctx & ctx) {
m_vector[m_idx] = m_old_value;
}
};
template<typename Ctx, typename D, typename R>
class insert_obj_map : public trail<Ctx> {
obj_map<D,R>& m_map;
D* m_obj;
public:
insert_obj_map(obj_map<D,R>& t, D* o) : m_map(t), m_obj(o) {}
virtual ~insert_obj_map() {}
virtual void undo(Ctx & ctx) { m_map.remove(m_obj); }
};
template<typename Ctx, typename M, typename D>
class insert_map : public trail<Ctx> {
M& m_map;
D m_obj;
public:
insert_map(M& t, D o) : m_map(t), m_obj(o) {}
virtual ~insert_map() {}
virtual void undo(Ctx & ctx) { m_map.remove(m_obj); }
};
template<typename Ctx, typename V>
class push_back_vector : public trail<Ctx> {
V & m_vector;
public:
push_back_vector(V & v):
m_vector(v) {
}
virtual void undo(Ctx & ctx) {
m_vector.pop_back();
}
};
template<typename Ctx, typename T>
class set_vector_idx_trail : public trail<Ctx> {
ptr_vector<T> & m_vector;
unsigned m_idx;
public:
set_vector_idx_trail(ptr_vector<T> & v, unsigned idx):
m_vector(v),
m_idx(idx) {
}
virtual ~set_vector_idx_trail() {
}
virtual void undo(Ctx & ctx) {
m_vector[m_idx] = 0;
}
};
template<typename Ctx, typename T, bool CallDestructors=true>
class pop_back_trail : public trail<Ctx> {
vector<T, CallDestructors> & m_vector;
T m_value;
public:
pop_back_trail(vector<T, CallDestructors> & v):
m_vector(v),
m_value(m_vector.back()) {
}
virtual void undo(Ctx & ctx) {
m_vector.push_back(m_value);
}
};
template<typename Ctx, typename T, bool CallDestructors=true>
class pop_back2_trail : public trail<Ctx> {
vector<T, CallDestructors> & m_vector;
typedef vector<vector<T, CallDestructors>, true> vector_t;
unsigned m_index;
T m_value;
public:
pop_back2_trail(vector<T, CallDestructors> & v, unsigned index):
m_vector(v),
m_index(index),
m_value(m_vector[index].back()) {
}
virtual void undo(Ctx & ctx) {
m_vector[m_index].push_back(m_value);
}
};
template<typename S, typename T>
class ast2ast_trailmap {
ref_vector<S, ast_manager> m_domain;
ref_vector<T, ast_manager> m_range;
obj_map<S, T*> m_map;
public:
ast2ast_trailmap(ast_manager& m):
m_domain(m),
m_range(m),
m_map()
{}
bool find(S* s, T*& t) {
return m_map.find(s,t);
}
void insert(S* s, T* t) {
SASSERT(!m_map.contains(s));
m_domain.push_back(s);
m_range.push_back(t);
m_map.insert(s,t);
}
void pop() {
SASSERT(!m_domain.empty());
m_map.remove(m_domain.back());
m_domain.pop_back();
m_range.pop_back();
}
};
template<typename Ctx, typename S, typename T>
class ast2ast_trail : public trail<Ctx> {
ast2ast_trailmap<S,T>& m_map;
public:
ast2ast_trail(ast2ast_trailmap<S,T>& m, S* s, T* t) :
m_map(m) {
m.insert(s,t);
}
virtual void undo(Ctx& ctx) {
m_map.pop();
}
};
template<typename Ctx, typename T, bool CallDestructors=true>
class push_back_trail : public trail<Ctx> {
vector<T, CallDestructors> & m_vector;
public:
push_back_trail(vector<T, CallDestructors> & v):
m_vector(v) {
}
virtual void undo(Ctx & ctx) {
m_vector.pop_back();
}
};
template<typename Ctx, typename T, bool CallDestructors=true>
class push_back2_trail : public trail<Ctx> {
typedef vector<vector<T, CallDestructors>, true> vector_t;
vector_t & m_vector;
unsigned m_index;
public:
push_back2_trail(vector_t & v, unsigned index) :
m_vector(v),
m_index(index) {
}
virtual void undo(Ctx & ctx) {
m_vector[m_index].pop_back();
}
};
template<typename Ctx>
class set_bitvector_trail : public trail<Ctx> {
svector<bool> & m_vector;
unsigned m_idx;
public:
set_bitvector_trail(svector<bool> & v, unsigned idx):
m_vector(v),
m_idx(idx) {
SASSERT(m_vector[m_idx] == false);
m_vector[m_idx] = true;
}
virtual void undo(Ctx & ctx) {
m_vector[m_idx] = false;
}
};
template<typename Ctx, typename T>
class new_obj_trail : public trail<Ctx> {
T * m_obj;
public:
new_obj_trail(T * obj):
m_obj(obj) {
}
virtual void undo(Ctx & ctx) {
dealloc(m_obj);
}
};
template<typename Ctx, typename M, typename T>
class obj_ref_trail : public trail<Ctx> {
obj_ref<T,M> m_obj;
public:
obj_ref_trail(obj_ref<T,M>& obj):
m_obj(obj) {
}
virtual void undo(Ctx & ctx) {
m_obj.reset();
}
};
template<typename Ctx, typename T>
class insert_obj_trail : public trail<Ctx> {
obj_hashtable<T>& m_table;
T* m_obj;
public:
insert_obj_trail(obj_hashtable<T>& t, T* o) : m_table(t), m_obj(o) {}
virtual ~insert_obj_trail() {}
virtual void undo(Ctx & ctx) { m_table.remove(m_obj); }
};
template<typename Ctx, typename T>
class remove_obj_trail : public trail<Ctx> {
obj_hashtable<T>& m_table;
T* m_obj;
public:
remove_obj_trail(obj_hashtable<T>& t, T* o) : m_table(t), m_obj(o) {}
virtual ~remove_obj_trail() {}
virtual void undo(Ctx & ctx) { m_table.insert(m_obj); }
};
template<typename Ctx>
void undo_trail_stack(Ctx & ctx, ptr_vector<trail<Ctx> > & s, unsigned old_size) {
SASSERT(old_size <= s.size());
typename ptr_vector<trail<Ctx> >::iterator begin = s.begin() + old_size;
typename ptr_vector<trail<Ctx> >::iterator it = s.end();
while (it != begin) {
--it;
(*it)->undo(ctx);
}
s.shrink(old_size);
}
template<typename Ctx>
class trail_stack {
Ctx & m_ctx;
ptr_vector<trail<Ctx> > m_trail_stack;
unsigned_vector m_scopes;
region m_region;
public:
trail_stack(Ctx & c):m_ctx(c) {}
~trail_stack() {}
region & get_region() { return m_region; }
void reset() {
pop_scope(m_scopes.size());
// Undo trail objects stored at lvl 0 (avoid memory leaks if lvl 0 contains new_obj_trail objects).
undo_trail_stack(m_ctx, m_trail_stack, 0);
}
void push_ptr(trail<Ctx> * t) { m_trail_stack.push_back(t); }
template<typename TrailObject>
void push(TrailObject const & obj) { m_trail_stack.push_back(new (m_region) TrailObject(obj)); }
unsigned get_num_scopes() const { return m_scopes.size(); }
void push_scope() { m_region.push_scope(); m_scopes.push_back(m_trail_stack.size()); }
void pop_scope(unsigned num_scopes) {
if (num_scopes == 0) return;
unsigned lvl = m_scopes.size();
SASSERT(num_scopes <= lvl);
unsigned new_lvl = lvl - num_scopes;
unsigned old_size = m_scopes[new_lvl];
undo_trail_stack(m_ctx, m_trail_stack, old_size);
m_scopes.shrink(new_lvl);
m_region.pop_scope(num_scopes);
}
};
#endif /* _TRAIL_H_ */