3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-07 18:05:21 +00:00

fix test build, working on rec-functions and automata complementation

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2016-03-01 22:31:44 -08:00
parent 9b6963d112
commit a25336a899
8 changed files with 241 additions and 59 deletions

View file

@ -326,6 +326,7 @@ cmd_context::cmd_context(bool main_ctx, ast_manager * m, symbol const & l):
m_manager(m),
m_own_manager(m == 0),
m_manager_initialized(false),
m_rec_fun_declared(false),
m_pmanager(0),
m_sexpr_manager(0),
m_regular("stdout", std::cout),
@ -830,14 +831,18 @@ void cmd_context::insert(symbol const & s, object_ref * r) {
}
void cmd_context::insert_rec_fun(func_decl* f, expr_ref_vector const& binding, svector<symbol> const& ids, expr* e) {
expr_ref eq(m()), lhs(m());
expr_ref eq(m());
app_ref lhs(m());
lhs = m().mk_app(f, binding.size(), binding.c_ptr());
eq = m().mk_eq(lhs, e);
if (!ids.empty()) {
eq = m().mk_forall(ids.size(), f->get_domain(), ids.c_ptr(), eq);
expr* pat = m().mk_pattern(lhs);
eq = m().mk_forall(ids.size(), f->get_domain(), ids.c_ptr(), eq, 0, symbol(":rec-fun"), symbol::null, 1, &pat);
}
if (!ids.empty() && !m_rec_fun_declared) {
warning_msg("recursive functions are currently only partially supported: they are translated into recursive equations without special handling");
m_rec_fun_declared = true;
}
warning_msg("recursive functions are currently only partially supported: they are translated into recursive equations without special handling");
// TBD: basic implementation asserts axiom. Life-time of recursive equation follows scopes (unlikely to be what SMT-LIB 2.5 wants).
assert_expr(eq);
}

View file

@ -165,6 +165,7 @@ protected:
ast_manager * m_manager;
bool m_own_manager;
bool m_manager_initialized;
bool m_rec_fun_declared;
pdecl_manager * m_pmanager;
sexpr_manager * m_sexpr_manager;
check_logic m_check_logic;

View file

@ -34,6 +34,9 @@ class symbolic_automata {
typedef vector<move_t> moves_t;
typedef obj_ref<T, M> ref_t;
typedef ref_vector<T, M> refs_t;
typedef std::pair<unsigned, unsigned> unsigned_pair;
template<class V> class u2_map : public map<unsigned_pair, V, pair_hash<unsigned_hash, unsigned_hash>, default_eq<unsigned_pair> > {};
M& m;
ba_t& m_ba;

View file

@ -25,7 +25,6 @@ Revision History:
#include "symbolic_automata.h"
#include "hashtable.h"
typedef std::pair<unsigned, unsigned> unsigned_pair;
@ -234,7 +233,7 @@ typename symbolic_automata<T, M>::automaton_t* symbolic_automata<T, M>::mk_minim
unsigned new_init = pblocks[blocks[a.init()]].get_representative();
// set moves
map<unsigned_pair, T*, pair_hash<unsigned_hash, unsigned_hash>, default_eq<unsigned_pair> > conds;
u2_map<T*> conds;
svector<unsigned_pair> keys;
moves_t new_moves;
@ -276,25 +275,22 @@ typename symbolic_automata<T, M>::automaton_t* symbolic_automata<T, M>::mk_minim
template<class T, class M>
typename symbolic_automata<T, M>::automaton_t* symbolic_automata<T, M>::mk_product(automaton_t& a, automaton_t& b) {
map<unsigned_pair, unsigned, pair_hash<unsigned_hash, unsigned_hash>, default_eq<unsigned_pair> > state_ids;
u2_map<unsigned> pair2id;
unsigned_pair init_pair(a.init(), b.init());
svector<unsigned_pair> todo;
todo.push_back(init_pair);
state_ids.insert(init_pair, 0);
pair2id.insert(init_pair, 0);
moves_t mvs;
unsigned_vector final;
if (a.is_final_state(a.init()) && b.is_final_state(b.init())) {
final.push_back(0);
}
if (false) {
mk_minimize(a);
}
unsigned n = 1;
moves_t mvsA, mvsB;
while (!todo.empty()) {
unsigned_pair curr_pair = todo.back();
todo.pop_back();
unsigned src = state_ids[curr_pair];
unsigned src = pair2id[curr_pair];
mvsA.reset(); mvsB.reset();
a.get_moves_from(curr_pair.first, mvsA, true);
b.get_moves_from(curr_pair.second, mvsB, true);
@ -310,9 +306,9 @@ typename symbolic_automata<T, M>::automaton_t* symbolic_automata<T, M>::mk_produ
}
unsigned_pair tgt_pair(mvsA[i].dst(), mvsB[j].dst());
unsigned tgt;
if (!state_ids.find(tgt_pair, tgt)) {
if (!pair2id.find(tgt_pair, tgt)) {
tgt = n++;
state_ids.insert(tgt_pair, tgt);
pair2id.insert(tgt_pair, tgt);
todo.push_back(tgt_pair);
if (a.is_final_state(tgt_pair.first) && b.is_final_state(tgt_pair.second)) {
final.push_back(tgt);
@ -366,6 +362,130 @@ typename symbolic_automata<T, M>::automaton_t* symbolic_automata<T, M>::mk_produ
}
}
#if 0
template<class T, class M>
unsigned symbolic_automata<T, M>::get_product_state_id(u2_map<unsigned>& pair2id, unsigned_pair const& p, unsigned& id) {
unsigned result = 0;
if (!pair2id.find(p, result)) {
result = id++;
pair2id.insert(p, result);
}
return result;
}
#endif
template<class T, class M>
typename symbolic_automata<T, M>::automaton_t* symbolic_automata<T, M>::mk_difference(automaton_t& a, automaton_t& b) {
#if 0
map<uint_set, unsigned, uint_set_hash, uint_set_eq> bs2id; // set of b-states to unique id
vector<uintset> id2bs; // unique id to set of b-states
u2_map<unsigned> pair2id; // pair of states to new state id
unsigned sink_state = UINT_MAX;
uint_set bset;
moves_t new_moves; // moves in the resulting automaton
unsigned_vector new_final_states; // new final states
unsigned p_state_id = 0; // next state identifier
bs2id.insert(uint_set(), sink_state); // the sink state has no b-states
bset.insert(b.init()); // the initial state has a single initial b state
bs2id.insert(bset, 0); // the index to the initial b state is 0
id2bs.push_back(bset);
if (!b.is_final_state(b.init()) && a.is_final_state(a.init())) {
new_final_states.push_back(p_state_id);
}
svector<unsigned_pair> todo;
unsigned_pair state(a.init(), 0);
todo.push_back(state);
pair2id.insert(state, p_state_id++);
// or just make todo a vector whose indices coincide with state_id.
while (!todo.empty()) {
state = todo.back();
unsigned state_id = pair2id[state];
todo.pop_back();
mvsA.reset();
a.get_moves_from(state.first, mvsA, true);
if (state.second == sink_state) {
for (unsigned i = 0; i < mvsA.size(); ++i) {
unsigned_pair dst(mvsA[i].dst(), sink_state);
bool is_new = !pair2id.contains(dst);
unsigned dst_id = get_product_state_id(pair2id, dst, p_state_id);
new_moves.push_back(move_t(m, state_id, dst_id, mvsA[i].t()));
if (is_new && a.is_final_state(mvsA[i].dst())) {
new_final_states.push_back(dst_id);
todo.push_back(dst);
}
}
}
else {
get_moves_from(b, id2bs[state.second], mvsB);
generate_min_terms(mvsB, min_terms);
for (unsigned j = 0; j < min_terms.size(); ++j) {
for (unsigned i = 0; i < mvsA.size(); ++i) {
ref_t cond(m_ba.mk_and(mvsA[i].t(), min_terms[j].second), m);
switch (m_ba.is_sat(cond)) {
case l_false:
break;
case l_true:
ab_combinations.push_back(ab_comb(i, min_terms[j].first, cond));
break;
case l_undef:
return 0;
}
}
}
for (unsigned i = 0; i < ab_combinations.size(); ++i) {
move_t const& mvA = mvsA[ab_combinations[i].A];
bset.reset();
bool is_final = a.is_final_state(mvA.dst());
for (unsigned j = 0; j < mvsB.size(); ++j) {
if (ab_combinations[i].B[j]) {
bset.insert(mvsB[j].dst());
is_final &= !b.is_final_state(mvsB[j].dst());
}
}
unsigned new_b;
if (bset.empty()) {
new_b = sink_state;
}
else if (!bs2id.find(bset, new_b)) {
new_b = id2bs.size();
id2bs.push_back(bset);
bs2id.insert(bset, new_b);
}
unsigned_pair dst(mvA.dst(), new_b);
bool is_new = !pair2id.contains(dst);
dst_id = get_product_state_id(pair2id, dst, p_state_id);
move_t new_move(m, state_id, dst_id, ab_combinations[i].cond);
new_moves.push_back(new_move);
if (is_new) {
if (is_final) {
new_final_states.push_back(dst_id);
}
todo.push_back(dst);
}
}
}
}
if (new_final_states.empty()) {
return alloc(automaton_t, m);
}
automaton_t* result = alloc(automaton_t, m, 0, new_final_states, new_moves);
#if 0
result->isEpsilonFree = true;
if (A.IsDeterministic)
result->isDeterministic = true;
result->EliminateDeadStates();
#endif
return result;
#endif
return 0;
}
#endif

View file

@ -31,7 +31,7 @@ Revision History:
namespace smt {
model_checker::model_checker(ast_manager & m, qi_params const & p, model_finder & mf):
m_manager(m),
m(m),
m_params(p),
m_qm(0),
m_context(0),
@ -93,9 +93,9 @@ namespace smt {
obj_hashtable<expr>::iterator end = universe.end();
for (; it != end; ++it) {
expr * e = *it;
eqs.push_back(m_manager.mk_eq(sk, e));
eqs.push_back(m.mk_eq(sk, e));
}
m_aux_context->assert_expr(m_manager.mk_or(eqs.size(), eqs.c_ptr()));
m_aux_context->assert_expr(m.mk_or(eqs.size(), eqs.c_ptr()));
}
#define PP_DEPTH 8
@ -106,16 +106,16 @@ namespace smt {
The variables are replaced by skolem constants. These constants are stored in sks.
*/
void model_checker::assert_neg_q_m(quantifier * q, expr_ref_vector & sks) {
expr_ref tmp(m_manager);
expr_ref tmp(m);
m_curr_model->eval(q->get_expr(), tmp, true);
TRACE("model_checker", tout << "q after applying interpretation:\n" << mk_ismt2_pp(tmp, m_manager) << "\n";);
TRACE("model_checker", tout << "q after applying interpretation:\n" << mk_ismt2_pp(tmp, m) << "\n";);
ptr_buffer<expr> subst_args;
unsigned num_decls = q->get_num_decls();
subst_args.resize(num_decls, 0);
sks.resize(num_decls, 0);
for (unsigned i = 0; i < num_decls; i++) {
sort * s = q->get_decl_sort(num_decls - i - 1);
expr * sk = m_manager.mk_fresh_const(0, s);
expr * sk = m.mk_fresh_const(0, s);
sks[num_decls - i - 1] = sk;
subst_args[num_decls - i - 1] = sk;
if (m_curr_model->is_finite(s)) {
@ -123,12 +123,12 @@ namespace smt {
}
}
expr_ref sk_body(m_manager);
var_subst s(m_manager);
expr_ref sk_body(m);
var_subst s(m);
s(tmp, subst_args.size(), subst_args.c_ptr(), sk_body);
expr_ref r(m_manager);
r = m_manager.mk_not(sk_body);
TRACE("model_checker", tout << "mk_neg_q_m:\n" << mk_ismt2_pp(r, m_manager) << "\n";);
expr_ref r(m);
r = m.mk_not(sk_body);
TRACE("model_checker", tout << "mk_neg_q_m:\n" << mk_ismt2_pp(r, m) << "\n";);
m_aux_context->assert_expr(r);
}
@ -138,13 +138,13 @@ namespace smt {
unsigned num_decls = q->get_num_decls();
// Remark: sks were created for the flat version of q.
SASSERT(sks.size() >= num_decls);
expr_ref_buffer bindings(m_manager);
expr_ref_vector bindings(m);
bindings.resize(num_decls);
unsigned max_generation = 0;
for (unsigned i = 0; i < num_decls; i++) {
expr * sk = sks.get(num_decls - i - 1);
func_decl * sk_d = to_app(sk)->get_decl();
expr_ref sk_value(m_manager);
expr_ref sk_value(m);
sk_value = cex->get_const_interp(sk_d);
if (sk_value == 0) {
sk_value = cex->get_some_value(sk_d->get_range());
@ -155,7 +155,7 @@ namespace smt {
unsigned sk_term_gen;
expr * sk_term = m_model_finder.get_inv(q, i, sk_value, sk_term_gen);
if (sk_term != 0) {
SASSERT(!m_manager.is_model_value(sk_term));
SASSERT(!m.is_model_value(sk_term));
if (sk_term_gen > max_generation)
max_generation = sk_term_gen;
sk_value = sk_term;
@ -177,27 +177,30 @@ namespace smt {
TRACE("model_checker", tout << q->get_qid() << " found (use_inv: " << use_inv << ") new instance: ";
for (unsigned i = 0; i < num_decls; i++) {
tout << mk_ismt2_pp(bindings[i], m_manager) << " ";
tout << mk_ismt2_pp(bindings[i].get(), m) << " ";
}
tout << "\n";);
for (unsigned i = 0; i < num_decls; i++)
add_instance(q, bindings, max_generation);
return true;
}
void model_checker::add_instance(quantifier* q, expr_ref_vector const& bindings, unsigned max_generation) {
for (unsigned i = 0; i < bindings.size(); i++)
m_new_instances_bindings.push_back(bindings[i]);
void * mem = m_new_instances_region.allocate(instance::get_obj_size(q->get_num_decls()));
instance * new_inst = new (mem) instance(q, bindings.c_ptr(), max_generation);
m_new_instances.push_back(new_inst);
return true;
}
void model_checker::operator()(expr *n) {
if (m_manager.is_model_value(n)) {
if (m.is_model_value(n)) {
throw is_model_value();
}
}
bool model_checker::contains_model_value(expr* n) {
if (m_manager.is_model_value(n)) {
if (m.is_model_value(n)) {
return true;
}
if (is_app(n) && to_app(n)->get_num_args() == 0) {
@ -217,22 +220,22 @@ namespace smt {
bool model_checker::add_blocking_clause(model * cex, expr_ref_vector & sks) {
SASSERT(cex != 0);
unsigned num_sks = sks.size();
expr_ref_buffer diseqs(m_manager);
expr_ref_buffer diseqs(m);
for (unsigned i = 0; i < num_sks; i++) {
expr * sk = sks.get(i);
func_decl * sk_d = to_app(sk)->get_decl();
expr_ref sk_value(m_manager);
expr_ref sk_value(m);
sk_value = cex->get_const_interp(sk_d);
if (sk_value == 0) {
sk_value = cex->get_some_value(sk_d->get_range());
if (sk_value == 0)
return false; // get_some_value failed... aborting add_blocking_clause
}
diseqs.push_back(m_manager.mk_not(m_manager.mk_eq(sk, sk_value)));
diseqs.push_back(m.mk_not(m.mk_eq(sk, sk_value)));
}
expr_ref blocking_clause(m_manager);
blocking_clause = m_manager.mk_or(diseqs.size(), diseqs.c_ptr());
TRACE("model_checker", tout << "blocking clause:\n" << mk_ismt2_pp(blocking_clause, m_manager) << "\n";);
expr_ref blocking_clause(m);
blocking_clause = m.mk_or(diseqs.size(), diseqs.c_ptr());
TRACE("model_checker", tout << "blocking clause:\n" << mk_ismt2_pp(blocking_clause, m) << "\n";);
m_aux_context->assert_expr(blocking_clause);
return true;
}
@ -245,15 +248,15 @@ namespace smt {
m_aux_context->push();
quantifier * flat_q = get_flat_quantifier(q);
TRACE("model_checker", tout << "model checking:\n" << mk_ismt2_pp(q->get_expr(), m_manager) << "\n" <<
mk_ismt2_pp(flat_q->get_expr(), m_manager) << "\n";);
expr_ref_vector sks(m_manager);
TRACE("model_checker", tout << "model checking:\n" << mk_ismt2_pp(q->get_expr(), m) << "\n" <<
mk_ismt2_pp(flat_q->get_expr(), m) << "\n";);
expr_ref_vector sks(m);
assert_neg_q_m(flat_q, sks);
TRACE("model_checker", tout << "skolems:\n";
for (unsigned i = 0; i < sks.size(); i++) {
expr * sk = sks.get(i);
tout << mk_ismt2_pp(sk, m_manager) << " " << mk_pp(m_manager.get_sort(sk), m_manager) << "\n";
tout << mk_ismt2_pp(sk, m) << " " << mk_pp(m.get_sort(sk), m) << "\n";
});
lbool r = m_aux_context->check();
@ -301,6 +304,43 @@ namespace smt {
return false;
}
bool model_checker::check_rec_fun(quantifier* q) {
TRACE("model_checker", tout << mk_pp(q, m) << "\n";);
SASSERT(q->get_num_patterns() == 1);
expr* fn = to_app(q->get_pattern(0))->get_arg(0);
SASSERT(is_app(fn));
func_decl* f = to_app(fn)->get_decl();
enode_vector::const_iterator it = m_context->begin_enodes_of(f);
enode_vector::const_iterator end = m_context->end_enodes_of(f);
bool is_undef = false;
expr_ref_vector args(m);
unsigned num_decls = q->get_num_decls();
args.resize(num_decls, 0);
var_subst sub(m);
expr_ref tmp(m), result(m);
for (; it != end; ++it) {
if (m_context->is_relevant(*it)) {
app* e = (*it)->get_owner();
for (unsigned i = 0; i < e->get_num_args(); ++i) {
args[num_decls - i - 1] = e->get_arg(i);
}
sub(q->get_expr(), num_decls, args.c_ptr(), tmp);
m_curr_model->eval(tmp, result, true);
if (m.is_true(result)) {
continue;
}
if (m.is_false(result)) {
add_instance(q, args, 0);
return false;
}
TRACE("model_checker", tout << tmp << "evaluates to undetermined " << result << "\n";);
is_undef = true;
}
}
return !is_undef;
}
void model_checker::init_aux_context() {
if (!m_fparams) {
m_fparams = alloc(smt_params, m_context->get_fparams());
@ -347,7 +387,7 @@ namespace smt {
quantifier * q = *it;
if(!m_qm->mbqi_enabled(q)) continue;
TRACE("model_checker",
tout << "Check: " << mk_pp(q, m_manager) << "\n";
tout << "Check: " << mk_pp(q, m) << "\n";
tout << m_context->get_assignment(q) << "\n";);
if (m_context->is_relevant(q) && m_context->get_assignment(q) == l_true) {
@ -355,7 +395,12 @@ namespace smt {
verbose_stream() << "(smt.mbqi :checking " << q->get_qid() << ")\n";
}
found_relevant = true;
if (!check(q)) {
if (q->get_qid() == symbol(":rec-fun")) {
if (!check_rec_fun(q)) {
num_failures++;
}
}
else if (!check(q)) {
if (m_params.m_mbqi_trace || get_verbosity_level() >= 5) {
verbose_stream() << "(smt.mbqi :failed " << q->get_qid() << ")\n";
}
@ -425,22 +470,22 @@ namespace smt {
for (unsigned i = 0; i < num_decls; i++) {
expr * b = inst->m_bindings[i];
if (!m_context->e_internalized(b)) {
TRACE("model_checker_bug_detail", tout << "internalizing b:\n" << mk_pp(b, m_manager) << "\n";);
TRACE("model_checker_bug_detail", tout << "internalizing b:\n" << mk_pp(b, m) << "\n";);
m_context->internalize(b, false, gen);
}
bindings.push_back(m_context->get_enode(b));
}
TRACE("model_checker_bug_detail", tout << "instantiating... q:\n" << mk_pp(q, m_manager) << "\n";
TRACE("model_checker_bug_detail", tout << "instantiating... q:\n" << mk_pp(q, m) << "\n";
tout << "inconsistent: " << m_context->inconsistent() << "\n";
tout << "bindings:\n";
for (unsigned i = 0; i < num_decls; i++) {
expr * b = inst->m_bindings[i];
tout << mk_pp(b, m_manager) << "\n";
tout << mk_pp(b, m) << "\n";
});
TRACE("model_checker_instance",
expr_ref inst_expr(m_manager);
instantiate(m_manager, q, inst->m_bindings, inst_expr);
tout << "(assert " << mk_ismt2_pp(inst_expr, m_manager) << ")\n";);
expr_ref inst_expr(m);
instantiate(m, q, inst->m_bindings, inst_expr);
tout << "(assert " << mk_ismt2_pp(inst_expr, m) << ")\n";);
m_context->add_instance(q, 0, num_decls, bindings.c_ptr(), gen, gen, gen, dummy);
TRACE("model_checker_bug_detail", tout << "after instantiating, inconsistent: " << m_context->inconsistent() << "\n";);
}

View file

@ -37,7 +37,7 @@ namespace smt {
class quantifier_manager;
class model_checker {
ast_manager & m_manager;
ast_manager & m; // _manager;
qi_params const & m_params;
// copy of smt_params for auxiliary context.
// the idea is to use a different configuration for the aux context (e.g., disable relevancy)
@ -59,7 +59,8 @@ namespace smt {
void assert_neg_q_m(quantifier * q, expr_ref_vector & sks);
bool add_blocking_clause(model * cex, expr_ref_vector & sks);
bool check(quantifier * q);
bool check_rec_fun(quantifier* q);
struct instance {
quantifier * m_q;
unsigned m_generation;
@ -82,6 +83,7 @@ namespace smt {
struct is_model_value {};
expr_mark m_visited;
bool contains_model_value(expr* e);
void add_instance(quantifier* q, expr_ref_vector const& bindings, unsigned max_generation);
public:
model_checker(ast_manager & m, qi_params const & p, model_finder & mf);

View file

@ -40,6 +40,7 @@ namespace smt {
ptr_vector<quantifier> m_quantifiers;
scoped_ptr<quantifier_manager_plugin> m_plugin;
unsigned m_num_instances;
symbol m_rec_fun;
imp(quantifier_manager & wrapper, context & ctx, smt_params & p, quantifier_manager_plugin * plugin):
m_wrapper(wrapper),
@ -47,7 +48,8 @@ namespace smt {
m_params(p),
m_qi_queue(m_wrapper, ctx, p),
m_qstat_gen(ctx.get_manager(), ctx.get_region()),
m_plugin(plugin) {
m_plugin(plugin),
m_rec_fun(":rec-fun") {
m_num_instances = 0;
m_qi_queue.setup();
}
@ -184,6 +186,10 @@ namespace smt {
m_qi_queue.instantiate();
}
bool check_quantifier(quantifier* q) {
return m_context.is_relevant(q) && m_context.get_assignment(q) == l_true; // TBD: && q->get_qid() != m_rec_fun;
}
bool quick_check_quantifiers() {
if (m_params.m_qi_quick_checker == MC_NO)
return true;
@ -195,7 +201,7 @@ namespace smt {
ptr_vector<quantifier>::const_iterator it = m_quantifiers.begin();
ptr_vector<quantifier>::const_iterator end = m_quantifiers.end();
for (; it != end; ++it)
if (m_context.is_relevant(*it) && m_context.get_assignment(*it) == l_true && mc.instantiate_unsat(*it))
if (check_quantifier(*it) && mc.instantiate_unsat(*it))
result = false;
if (m_params.m_qi_quick_checker == MC_UNSAT || !result) {
m_qi_queue.instantiate();
@ -206,7 +212,7 @@ namespace smt {
IF_VERBOSE(10, verbose_stream() << "quick checking quantifiers (not sat)...\n";);
it = m_quantifiers.begin();
for (; it != end; ++it)
if (m_context.is_relevant(*it) && m_context.get_assignment(*it) == l_true && mc.instantiate_not_sat(*it))
if (check_quantifier(*it) && mc.instantiate_not_sat(*it))
result = false;
m_qi_queue.instantiate();
return result;

View file

@ -38,7 +38,7 @@ void tst_expr_arith(unsigned num_files) {
er.get_next(m.mk_bool_sort(), e);
ast_smt_pp pp(m);
pp.set_logic("QF_AUFLIA");
pp.set_logic(symbol("QF_AUFLIA"));
std::ostringstream buffer;
buffer << "random_arith_" << i << ".smt";
std::cout << buffer.str() << "\n";
@ -81,7 +81,7 @@ void tst_expr_rand(unsigned num_files) {
er.get_next(m.mk_bool_sort(), e);
ast_smt_pp pp(m);
pp.set_logic("QF_AUFBV");
pp.set_logic(symbol("QF_AUFBV"));
std::ostringstream buffer;
buffer << "random_bv_" << i << ".smt";
std::cout << buffer.str() << "\n";