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:
parent
4722fdfca5
commit
add684d8e9
377 changed files with 204 additions and 62 deletions
77
src/ast/expr2var.cpp
Normal file
77
src/ast/expr2var.cpp
Normal 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
75
src/ast/expr2var.h
Normal 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
97
src/ast/expr_abstract.cpp
Normal 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
28
src/ast/expr_abstract.h
Normal 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
142
src/ast/expr_functors.cpp
Normal 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
121
src/ast/expr_functors.h
Normal 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
88
src/ast/expr_stat.cpp
Normal 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
50
src/ast/expr_stat.h
Normal 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
604
src/ast/static_features.cpp
Normal 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
169
src/ast/static_features.h
Normal 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
404
src/ast/trail.h
Normal 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_ */
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue