mirror of
https://github.com/Z3Prover/z3
synced 2025-04-22 16:45:31 +00:00
Z3 sources
Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
parent
3f9edad676
commit
e9eab22e5c
1186 changed files with 381859 additions and 0 deletions
224
lib/act_cache.cpp
Normal file
224
lib/act_cache.cpp
Normal file
|
@ -0,0 +1,224 @@
|
|||
/*++
|
||||
Copyright (c) 2011 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
act_cache.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
expr -> expr activity cache
|
||||
It maintains at most N unused entries
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo (leonardo) 2011-04-12
|
||||
|
||||
Notes:
|
||||
|
||||
--*/
|
||||
#include"act_cache.h"
|
||||
|
||||
#define MIN_MAX_UNUSED 1024
|
||||
#define INITIAL_CAPACITY 128
|
||||
|
||||
/*
|
||||
This cache is a mapping from expr -> tagged expressions
|
||||
A tagged expression is essentially a pair (expr, flag)
|
||||
Thus, an entry
|
||||
t -> (s, 0)
|
||||
maps the key t to value s, and says that key t was never accessed.
|
||||
That is, client code never executed find(t)
|
||||
Similarly, an entry
|
||||
t -> (s, 1)
|
||||
also maps the key t to value s, but signs that key t was already accessed
|
||||
by client code.
|
||||
|
||||
When a new key/value pair is inserted the flag is 0.
|
||||
The flag is set to 1 after the key is accessed.
|
||||
|
||||
The number of unused entries (m_unused) is equal to the number of entries
|
||||
of the form
|
||||
t -> (s, 0)
|
||||
That is, it is the number of keys that were never accessed by cliend code.
|
||||
|
||||
The cache maintains at most m_max_unused entries.
|
||||
When the maximum number of unused entries exceeds m_max_unused, then
|
||||
the cache will delete the oldest unused entry.
|
||||
*/
|
||||
|
||||
/**
|
||||
m_queue stores the recently added keys.
|
||||
The queue is implemented as pair: m_queue (vector), m_qhead (unsigned).
|
||||
The "active" part of m_queue is the range [m_qhead, m_queue.size())
|
||||
The "inactive" part [0, m_qhead) contains keys that were already used by client code.
|
||||
This procedure, deletes the inactive part, and makes m_qhead == 0.
|
||||
*/
|
||||
void act_cache::compress_queue() {
|
||||
SASSERT(m_qhead > 0);
|
||||
unsigned sz = m_queue.size();
|
||||
unsigned j = 0;
|
||||
for (unsigned i = m_qhead; i < sz; i++, j++) {
|
||||
m_queue[j] = m_queue[i];
|
||||
}
|
||||
m_queue.shrink(j);
|
||||
m_qhead = 0;
|
||||
}
|
||||
|
||||
void act_cache::init() {
|
||||
if (m_max_unused < MIN_MAX_UNUSED)
|
||||
m_max_unused = MIN_MAX_UNUSED;
|
||||
m_unused = 0;
|
||||
m_qhead = 0;
|
||||
}
|
||||
|
||||
void act_cache::dec_refs() {
|
||||
map::iterator it = m_table.begin();
|
||||
map::iterator end = m_table.end();
|
||||
for (; it != end; ++it) {
|
||||
m_manager.dec_ref((*it).m_key);
|
||||
m_manager.dec_ref(UNTAG(expr*, (*it).m_value));
|
||||
}
|
||||
}
|
||||
|
||||
act_cache::act_cache(ast_manager & m):
|
||||
m_manager(m),
|
||||
m_max_unused(m.get_num_asts()) {
|
||||
init();
|
||||
}
|
||||
|
||||
act_cache::act_cache(ast_manager & m, unsigned max_unused):
|
||||
m_manager(m),
|
||||
m_max_unused(max_unused) {
|
||||
init();
|
||||
}
|
||||
|
||||
act_cache::~act_cache() {
|
||||
dec_refs();
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Search m_queue from [m_qhead, m_queue.size()) until it finds
|
||||
an unused key. That is a key associated with an entry
|
||||
key -> (value, 0)
|
||||
*/
|
||||
void act_cache::del_unused() {
|
||||
unsigned sz = m_queue.size();
|
||||
while (m_qhead < sz) {
|
||||
expr * k = m_queue[m_qhead];
|
||||
m_qhead++;
|
||||
SASSERT(m_table.contains(k));
|
||||
map::key_value * entry = m_table.find_core(k);
|
||||
SASSERT(entry);
|
||||
if (GET_TAG(entry->m_value) == 0) {
|
||||
// Key k was never accessed by client code.
|
||||
// That is, find(k) was never executed by client code.
|
||||
m_unused--;
|
||||
expr * v = entry->m_value;
|
||||
m_table.erase(k);
|
||||
m_manager.dec_ref(k);
|
||||
m_manager.dec_ref(v);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (m_qhead == sz) {
|
||||
// The "active" part of the queue is empty.
|
||||
// So, we perform a "cheap" compress.
|
||||
m_queue.reset();
|
||||
m_qhead = 0;
|
||||
}
|
||||
else if (m_qhead > m_max_unused) {
|
||||
compress_queue();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Insert a new entry k -> v into the cache.
|
||||
*/
|
||||
void act_cache::insert(expr * k, expr * v) {
|
||||
SASSERT(k);
|
||||
if (m_unused >= m_max_unused)
|
||||
del_unused();
|
||||
expr * dummy = reinterpret_cast<expr*>(1);
|
||||
map::key_value & entry = m_table.insert_if_not_there(k, dummy);
|
||||
#if 0
|
||||
unsigned static counter = 0;
|
||||
counter++;
|
||||
if (counter % 100000 == 0)
|
||||
verbose_stream() << "[act-cache] counter: " << counter << " used_slots: " << m_table.used_slots() << " capacity: " << m_table.capacity() << " size: " << m_table.size() << " collisions: " << m_table.collisions() << "\n";
|
||||
#endif
|
||||
|
||||
#ifdef Z3DEBUG
|
||||
unsigned expected_tag;
|
||||
#endif
|
||||
if (entry.m_value == dummy) {
|
||||
// new entry;
|
||||
m_manager.inc_ref(k);
|
||||
m_manager.inc_ref(v);
|
||||
entry.m_value = v;
|
||||
m_queue.push_back(k);
|
||||
m_unused++;
|
||||
DEBUG_CODE(expected_tag = 0;); // new entry
|
||||
}
|
||||
else if (UNTAG(expr*, entry.m_value) == v) {
|
||||
// already there
|
||||
DEBUG_CODE(expected_tag = GET_TAG(entry.m_value););
|
||||
}
|
||||
else {
|
||||
// replacing old entry
|
||||
m_manager.inc_ref(v);
|
||||
m_manager.dec_ref(UNTAG(expr*, entry.m_value));
|
||||
entry.m_value = v;
|
||||
SASSERT(GET_TAG(entry.m_value) == 0);
|
||||
// replaced old entry, and reset the tag.
|
||||
DEBUG_CODE(expected_tag = 0;);
|
||||
}
|
||||
DEBUG_CODE({
|
||||
expr * v2;
|
||||
SASSERT(m_table.find(k, v2));
|
||||
SASSERT(v == UNTAG(expr*, v2));
|
||||
SASSERT(expected_tag == GET_TAG(v2));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Search for key k in the cache.
|
||||
If entry k -> (v, tag) is found, we set tag to 1.
|
||||
*/
|
||||
expr * act_cache::find(expr * k) {
|
||||
map::key_value * entry = m_table.find_core(k);
|
||||
if (entry == 0)
|
||||
return 0;
|
||||
if (GET_TAG(entry->m_value) == 0) {
|
||||
entry->m_value = TAG(expr*, entry->m_value, 1);
|
||||
SASSERT(GET_TAG(entry->m_value) == 1);
|
||||
SASSERT(m_unused > 0);
|
||||
m_unused--;
|
||||
DEBUG_CODE({
|
||||
expr * v;
|
||||
SASSERT(m_table.find(k, v));
|
||||
SASSERT(GET_TAG(v) == 1);
|
||||
});
|
||||
}
|
||||
return UNTAG(expr*, entry->m_value);
|
||||
}
|
||||
|
||||
void act_cache::reset() {
|
||||
dec_refs();
|
||||
m_table.reset();
|
||||
m_queue.reset();
|
||||
m_unused = 0;
|
||||
m_qhead = 0;
|
||||
}
|
||||
|
||||
void act_cache::cleanup() {
|
||||
dec_refs();
|
||||
m_table.finalize();
|
||||
m_queue.finalize();
|
||||
m_unused = 0;
|
||||
m_qhead = 0;
|
||||
}
|
||||
|
||||
bool act_cache::check_invariant() const {
|
||||
return true;
|
||||
}
|
56
lib/act_cache.h
Normal file
56
lib/act_cache.h
Normal file
|
@ -0,0 +1,56 @@
|
|||
/*++
|
||||
Copyright (c) 2011 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
act_cache.h
|
||||
|
||||
Abstract:
|
||||
|
||||
expr -> expr activity cache
|
||||
It maintains at most N unused entries
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo (leonardo) 2011-04-12
|
||||
|
||||
Notes:
|
||||
|
||||
--*/
|
||||
#ifndef _ACT_CACHE_H_
|
||||
#define _ACT_CACHE_H_
|
||||
|
||||
#include"ast.h"
|
||||
#include"obj_hashtable.h"
|
||||
#include"chashtable.h"
|
||||
|
||||
class act_cache {
|
||||
ast_manager & m_manager;
|
||||
typedef cmap<expr*, expr*, obj_ptr_hash<expr>, default_eq<expr*> > map;
|
||||
map m_table;
|
||||
ptr_vector<expr> m_queue; // recently created queue
|
||||
unsigned m_qhead;
|
||||
unsigned m_unused;
|
||||
unsigned m_max_unused;
|
||||
|
||||
void compress_queue();
|
||||
void init();
|
||||
void dec_refs();
|
||||
void del_unused();
|
||||
|
||||
public:
|
||||
act_cache(ast_manager & m);
|
||||
act_cache(ast_manager & m, unsigned max_unused);
|
||||
~act_cache();
|
||||
void insert(expr * k, expr * v);
|
||||
expr * find(expr * k);
|
||||
void reset();
|
||||
void cleanup();
|
||||
unsigned size() const { return m_table.size(); }
|
||||
unsigned capacity() const { return m_table.capacity(); }
|
||||
bool empty() const { return m_table.empty(); }
|
||||
bool check_invariant() const;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
164
lib/add_bounds.cpp
Normal file
164
lib/add_bounds.cpp
Normal file
|
@ -0,0 +1,164 @@
|
|||
/*++
|
||||
Copyright (c) 2011 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
add_bounds.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Strategy for bounding unbounded variables.
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2011-06-30.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include"add_bounds.h"
|
||||
#include"arith_decl_plugin.h"
|
||||
#include"ast_smt2_pp.h"
|
||||
#include"bound_manager.h"
|
||||
#include"for_each_expr.h"
|
||||
#include"assertion_set_util.h"
|
||||
|
||||
struct is_unbounded_proc {
|
||||
struct found {};
|
||||
arith_util m_util;
|
||||
bound_manager & m_bm;
|
||||
|
||||
is_unbounded_proc(bound_manager & bm):m_util(bm.m()), m_bm(bm) {}
|
||||
|
||||
void operator()(app * t) {
|
||||
if (is_uninterp_const(t) && (m_util.is_int(t) || m_util.is_real(t)) && (!m_bm.has_lower(t) || !m_bm.has_upper(t)))
|
||||
throw found();
|
||||
}
|
||||
|
||||
void operator()(var *) {}
|
||||
|
||||
void operator()(quantifier*) {}
|
||||
};
|
||||
|
||||
bool is_unbounded(assertion_set const & s) {
|
||||
ast_manager & m = s.m();
|
||||
bound_manager bm(m);
|
||||
bm(s);
|
||||
is_unbounded_proc proc(bm);
|
||||
return test(s, proc);
|
||||
}
|
||||
|
||||
struct add_bounds::imp {
|
||||
ast_manager & m;
|
||||
rational m_lower;
|
||||
rational m_upper;
|
||||
volatile bool m_cancel;
|
||||
|
||||
imp(ast_manager & _m, params_ref const & p):
|
||||
m(_m) {
|
||||
updt_params(p);
|
||||
}
|
||||
|
||||
void updt_params(params_ref const & p) {
|
||||
m_lower = p.get_rat(":add-bound-lower", rational(-2));
|
||||
m_upper = p.get_rat(":add-bound-upper", rational(2));
|
||||
}
|
||||
|
||||
void set_cancel(bool f) {
|
||||
m_cancel = f;
|
||||
}
|
||||
|
||||
struct add_bound_proc {
|
||||
arith_util m_util;
|
||||
bound_manager & m_bm;
|
||||
assertion_set & m_set;
|
||||
rational const & m_lower;
|
||||
rational const & m_upper;
|
||||
unsigned m_num_bounds;
|
||||
|
||||
add_bound_proc(bound_manager & bm, assertion_set & s, rational const & l, rational const & u):
|
||||
m_util(bm.m()),
|
||||
m_bm(bm),
|
||||
m_set(s),
|
||||
m_lower(l),
|
||||
m_upper(u) {
|
||||
m_num_bounds = 0;
|
||||
}
|
||||
|
||||
void operator()(app * t) {
|
||||
if (is_uninterp_const(t) && (m_util.is_int(t) || m_util.is_real(t))) {
|
||||
if (!m_bm.has_lower(t)) {
|
||||
m_set.assert_expr(m_util.mk_le(t, m_util.mk_numeral(m_upper, m_util.is_int(t))));
|
||||
m_num_bounds++;
|
||||
}
|
||||
if (!m_bm.has_upper(t)) {
|
||||
m_set.assert_expr(m_util.mk_ge(t, m_util.mk_numeral(m_lower, m_util.is_int(t))));
|
||||
m_num_bounds++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void operator()(var *) {}
|
||||
|
||||
void operator()(quantifier*) {}
|
||||
};
|
||||
|
||||
void operator()(assertion_set & s, model_converter_ref & mc) {
|
||||
mc = 0;
|
||||
if (s.inconsistent())
|
||||
return;
|
||||
as_st_report report("add-bounds", s);
|
||||
bound_manager bm(m);
|
||||
expr_fast_mark1 visited;
|
||||
add_bound_proc proc(bm, s, m_lower, m_upper);
|
||||
unsigned sz = s.size();
|
||||
for (unsigned i = 0; i < sz; i++)
|
||||
quick_for_each_expr(proc, visited, s.form(i));
|
||||
visited.reset();
|
||||
report_st_progress(":added-bounds", proc.m_num_bounds);
|
||||
TRACE("add_bounds", s.display(tout););
|
||||
}
|
||||
};
|
||||
|
||||
add_bounds::add_bounds(ast_manager & m, params_ref const & p):
|
||||
m_params(p) {
|
||||
m_imp = alloc(imp, m, p);
|
||||
}
|
||||
|
||||
add_bounds::~add_bounds() {
|
||||
dealloc(m_imp);
|
||||
}
|
||||
|
||||
void add_bounds::updt_params(params_ref const & p) {
|
||||
m_params = p;
|
||||
m_imp->updt_params(p);
|
||||
}
|
||||
|
||||
void add_bounds::get_param_descrs(param_descrs & r) {
|
||||
r.insert(":add-bound-lower", CPK_NUMERAL, "(default: -2) lower bound to be added to unbounded variables.");
|
||||
r.insert(":add-bound-upper", CPK_NUMERAL, "(default: 2) upper bound to be added to unbounded variables.");
|
||||
}
|
||||
|
||||
void add_bounds::operator()(assertion_set & s, model_converter_ref & mc) {
|
||||
m_imp->operator()(s, mc);
|
||||
}
|
||||
|
||||
void add_bounds::set_cancel(bool f) {
|
||||
if (m_imp)
|
||||
m_imp->set_cancel(f);
|
||||
}
|
||||
|
||||
void add_bounds::cleanup() {
|
||||
ast_manager & m = m_imp->m;
|
||||
imp * d = m_imp;
|
||||
#pragma omp critical (as_st_cancel)
|
||||
{
|
||||
d = m_imp;
|
||||
}
|
||||
dealloc(d);
|
||||
d = alloc(imp, m, m_params);
|
||||
#pragma omp critical (as_st_cancel)
|
||||
{
|
||||
m_imp = d;
|
||||
}
|
||||
}
|
50
lib/add_bounds.h
Normal file
50
lib/add_bounds.h
Normal file
|
@ -0,0 +1,50 @@
|
|||
/*++
|
||||
Copyright (c) 2011 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
add_bounds.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Strategy for bounding unbounded variables.
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2011-06-30.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _ADD_BOUNDS_H_
|
||||
#define _ADD_BOUNDS_H_
|
||||
|
||||
#include"assertion_set_strategy.h"
|
||||
|
||||
bool is_unbounded(assertion_set const & s);
|
||||
|
||||
class add_bounds : public assertion_set_strategy {
|
||||
struct imp;
|
||||
imp * m_imp;
|
||||
params_ref m_params;
|
||||
public:
|
||||
add_bounds(ast_manager & m, params_ref const & p = params_ref());
|
||||
virtual ~add_bounds();
|
||||
|
||||
virtual void updt_params(params_ref const & p);
|
||||
static void get_param_descrs(param_descrs & r);
|
||||
virtual void collect_param_descrs(param_descrs & r) { get_param_descrs(r); }
|
||||
|
||||
virtual void operator()(assertion_set & s, model_converter_ref & mc);
|
||||
|
||||
virtual void cleanup();
|
||||
|
||||
protected:
|
||||
virtual void set_cancel(bool f);
|
||||
};
|
||||
|
||||
inline as_st * mk_add_bounds(ast_manager & m, params_ref const & p = params_ref()) {
|
||||
return clean(alloc(add_bounds, m, p));
|
||||
}
|
||||
|
||||
#endif
|
198
lib/add_bounds_tactic.cpp
Normal file
198
lib/add_bounds_tactic.cpp
Normal file
|
@ -0,0 +1,198 @@
|
|||
/*++
|
||||
Copyright (c) 2011 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
add_bounds_tactic.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Tactic for bounding unbounded variables.
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2011-10-22.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include"tactical.h"
|
||||
#include"arith_decl_plugin.h"
|
||||
#include"ast_smt2_pp.h"
|
||||
#include"bound_manager.h"
|
||||
|
||||
struct is_unbounded_proc {
|
||||
struct found {};
|
||||
arith_util m_util;
|
||||
bound_manager & m_bm;
|
||||
|
||||
is_unbounded_proc(bound_manager & bm):m_util(bm.m()), m_bm(bm) {}
|
||||
|
||||
void operator()(app * t) {
|
||||
if (is_uninterp_const(t) && (m_util.is_int(t) || m_util.is_real(t)) && (!m_bm.has_lower(t) || !m_bm.has_upper(t)))
|
||||
throw found();
|
||||
}
|
||||
|
||||
void operator()(var *) {}
|
||||
|
||||
void operator()(quantifier*) {}
|
||||
};
|
||||
|
||||
bool is_unbounded(goal const & g) {
|
||||
ast_manager & m = g.m();
|
||||
bound_manager bm(m);
|
||||
bm(g);
|
||||
is_unbounded_proc proc(bm);
|
||||
return test(g, proc);
|
||||
}
|
||||
|
||||
class is_unbounded_probe : public probe {
|
||||
public:
|
||||
virtual result operator()(goal const & g) {
|
||||
return is_unbounded(g);
|
||||
}
|
||||
};
|
||||
|
||||
probe * mk_is_unbounded_probe() {
|
||||
return alloc(is_unbounded_probe);
|
||||
}
|
||||
|
||||
class add_bounds_tactic : public tactic {
|
||||
struct imp {
|
||||
ast_manager & m;
|
||||
rational m_lower;
|
||||
rational m_upper;
|
||||
volatile bool m_cancel;
|
||||
|
||||
imp(ast_manager & _m, params_ref const & p):
|
||||
m(_m) {
|
||||
updt_params(p);
|
||||
}
|
||||
|
||||
void updt_params(params_ref const & p) {
|
||||
m_lower = p.get_rat(":add-bound-lower", rational(-2));
|
||||
m_upper = p.get_rat(":add-bound-upper", rational(2));
|
||||
}
|
||||
|
||||
void set_cancel(bool f) {
|
||||
m_cancel = f;
|
||||
}
|
||||
|
||||
struct add_bound_proc {
|
||||
arith_util m_util;
|
||||
bound_manager & m_bm;
|
||||
goal & m_goal;
|
||||
rational const & m_lower;
|
||||
rational const & m_upper;
|
||||
unsigned m_num_bounds;
|
||||
|
||||
add_bound_proc(bound_manager & bm, goal & g, rational const & l, rational const & u):
|
||||
m_util(bm.m()),
|
||||
m_bm(bm),
|
||||
m_goal(g),
|
||||
m_lower(l),
|
||||
m_upper(u) {
|
||||
m_num_bounds = 0;
|
||||
}
|
||||
|
||||
void operator()(app * t) {
|
||||
if (is_uninterp_const(t) && (m_util.is_int(t) || m_util.is_real(t))) {
|
||||
if (!m_bm.has_lower(t)) {
|
||||
m_goal.assert_expr(m_util.mk_le(t, m_util.mk_numeral(m_upper, m_util.is_int(t))));
|
||||
m_num_bounds++;
|
||||
}
|
||||
if (!m_bm.has_upper(t)) {
|
||||
m_goal.assert_expr(m_util.mk_ge(t, m_util.mk_numeral(m_lower, m_util.is_int(t))));
|
||||
m_num_bounds++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void operator()(var *) {}
|
||||
|
||||
void operator()(quantifier*) {}
|
||||
};
|
||||
|
||||
virtual void operator()(goal_ref const & g,
|
||||
goal_ref_buffer & result,
|
||||
model_converter_ref & mc,
|
||||
proof_converter_ref & pc,
|
||||
expr_dependency_ref & core) {
|
||||
mc = 0; pc = 0; core = 0;
|
||||
tactic_report report("add-bounds", *g);
|
||||
bound_manager bm(m);
|
||||
expr_fast_mark1 visited;
|
||||
add_bound_proc proc(bm, *(g.get()), m_lower, m_upper);
|
||||
unsigned sz = g->size();
|
||||
for (unsigned i = 0; i < sz; i++)
|
||||
quick_for_each_expr(proc, visited, g->form(i));
|
||||
visited.reset();
|
||||
g->inc_depth();
|
||||
result.push_back(g.get());
|
||||
if (proc.m_num_bounds > 0)
|
||||
g->updt_prec(goal::UNDER);
|
||||
report_tactic_progress(":added-bounds", proc.m_num_bounds);
|
||||
TRACE("add_bounds", g->display(tout););
|
||||
}
|
||||
};
|
||||
|
||||
imp * m_imp;
|
||||
params_ref m_params;
|
||||
|
||||
public:
|
||||
add_bounds_tactic(ast_manager & m, params_ref const & p):
|
||||
m_params(p) {
|
||||
m_imp = alloc(imp, m, p);
|
||||
}
|
||||
|
||||
virtual tactic * translate(ast_manager & m) {
|
||||
return alloc(add_bounds_tactic, m, m_params);
|
||||
}
|
||||
|
||||
virtual ~add_bounds_tactic() {
|
||||
dealloc(m_imp);
|
||||
}
|
||||
|
||||
virtual void updt_params(params_ref const & p) {
|
||||
m_params = p;
|
||||
m_imp->updt_params(p);
|
||||
}
|
||||
|
||||
virtual void collect_param_descrs(param_descrs & r) {
|
||||
r.insert(":add-bound-lower", CPK_NUMERAL, "(default: -2) lower bound to be added to unbounded variables.");
|
||||
r.insert(":add-bound-upper", CPK_NUMERAL, "(default: 2) upper bound to be added to unbounded variables.");
|
||||
}
|
||||
|
||||
virtual void operator()(goal_ref const & g,
|
||||
goal_ref_buffer & result,
|
||||
model_converter_ref & mc,
|
||||
proof_converter_ref & pc,
|
||||
expr_dependency_ref & core) {
|
||||
(*m_imp)(g, result, mc, pc, core);
|
||||
}
|
||||
|
||||
virtual void cleanup() {
|
||||
ast_manager & m = m_imp->m;
|
||||
imp * d = m_imp;
|
||||
#pragma omp critical (tactic_cancel)
|
||||
{
|
||||
d = m_imp;
|
||||
}
|
||||
dealloc(d);
|
||||
d = alloc(imp, m, m_params);
|
||||
#pragma omp critical (tactic_cancel)
|
||||
{
|
||||
m_imp = d;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void set_cancel(bool f) {
|
||||
if (m_imp)
|
||||
m_imp->set_cancel(f);
|
||||
}
|
||||
};
|
||||
|
||||
tactic * mk_add_bounds_tactic(ast_manager & m, params_ref const & p) {
|
||||
return clean(alloc(add_bounds_tactic, m, p));
|
||||
}
|
34
lib/add_bounds_tactic.h
Normal file
34
lib/add_bounds_tactic.h
Normal file
|
@ -0,0 +1,34 @@
|
|||
/*++
|
||||
Copyright (c) 2011 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
add_bounds.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Tactic for bounding unbounded variables.
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2011-06-30.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _ADD_BOUNDS_H_
|
||||
#define _ADD_BOUNDS_H_
|
||||
|
||||
#include"params.h"
|
||||
|
||||
class ast_manager;
|
||||
class goal;
|
||||
class tactic;
|
||||
class probe;
|
||||
|
||||
bool is_unbounded(goal const & g);
|
||||
probe * mk_is_unbounded_probe();
|
||||
|
||||
tactic * mk_add_bounds_tactic(ast_manager & m, params_ref const & p = params_ref());
|
||||
|
||||
#endif
|
1812
lib/aig.cpp
Normal file
1812
lib/aig.cpp
Normal file
File diff suppressed because it is too large
Load diff
85
lib/aig.h
Normal file
85
lib/aig.h
Normal file
|
@ -0,0 +1,85 @@
|
|||
/*++
|
||||
Copyright (c) 2011 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
aig.h
|
||||
|
||||
Abstract:
|
||||
|
||||
And-inverted graphs
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo (leonardo) 2011-05-13
|
||||
|
||||
Notes:
|
||||
|
||||
--*/
|
||||
#ifndef _AIG_H_
|
||||
#define _AIG_H_
|
||||
|
||||
#include"ast.h"
|
||||
#include"tactic_exception.h"
|
||||
|
||||
class assertion_set;
|
||||
class goal;
|
||||
class aig_lit;
|
||||
class aig_manager;
|
||||
|
||||
class aig_exception : public tactic_exception {
|
||||
public:
|
||||
aig_exception(char const * msg):tactic_exception(msg) {}
|
||||
};
|
||||
|
||||
class aig_ref {
|
||||
friend class aig_lit;
|
||||
friend class aig_manager;
|
||||
aig_manager * m_manager;
|
||||
void * m_ref;
|
||||
aig_ref(aig_manager & m, aig_lit const & l);
|
||||
public:
|
||||
aig_ref();
|
||||
~aig_ref();
|
||||
aig_ref & operator=(aig_ref const & r);
|
||||
bool operator==(aig_ref const & r) const { return m_ref == r.m_ref; }
|
||||
bool operator!=(aig_ref const & r) const { return m_ref != r.m_ref; }
|
||||
};
|
||||
|
||||
class aig_manager {
|
||||
struct imp;
|
||||
imp * m_imp;
|
||||
friend class aig_ref;
|
||||
public:
|
||||
// If default_gate_encoding == true, then
|
||||
// ite(a, b, c) is encoded as (NOT a OR b) AND (a OR c)
|
||||
// iff(a, b) is encoded as (NOT a OR b) AND (a OR NOT b)
|
||||
//
|
||||
// If default_gate_encoding == false, then
|
||||
// ite(a, b, c) is encoded as (a AND b) OR (NOT a AND c)
|
||||
// iff(a, b) is encoded as (a AND b) OR (NOT a AND NOT b)
|
||||
aig_manager(ast_manager & m, unsigned long long max_memory = UINT64_MAX, bool default_gate_encoding = true);
|
||||
~aig_manager();
|
||||
void set_max_memory(unsigned long long max);
|
||||
aig_ref mk_aig(expr * n);
|
||||
aig_ref mk_aig(assertion_set const & s); // TODO delete
|
||||
aig_ref mk_aig(goal const & g);
|
||||
aig_ref mk_not(aig_ref const & r);
|
||||
aig_ref mk_and(aig_ref const & r1, aig_ref const & r2);
|
||||
aig_ref mk_or(aig_ref const & r1, aig_ref const & r2);
|
||||
aig_ref mk_iff(aig_ref const & r1, aig_ref const & r2);
|
||||
aig_ref mk_ite(aig_ref const & r1, aig_ref const & r2, aig_ref const & r3);
|
||||
void max_sharing(aig_ref & r);
|
||||
void to_formula(aig_ref const & r, assertion_set & s); // TODO delete
|
||||
void to_formula(aig_ref const & r, expr_ref & result);
|
||||
void to_formula(aig_ref const & r, goal & result);
|
||||
void to_cnf(aig_ref const & r, goal & result);
|
||||
void display(std::ostream & out, aig_ref const & r) const;
|
||||
void display_smt2(std::ostream & out, aig_ref const & r) const;
|
||||
unsigned get_num_aigs() const;
|
||||
void cancel() { set_cancel(true); }
|
||||
void reset_cancel() { set_cancel(false); }
|
||||
void set_cancel(bool f);
|
||||
};
|
||||
|
||||
#endif
|
126
lib/aig_tactic.cpp
Normal file
126
lib/aig_tactic.cpp
Normal file
|
@ -0,0 +1,126 @@
|
|||
/*++
|
||||
Copyright (c) 2011 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
aig_tactic.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Tactic for minimizing circuits using AIGs.
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo (leonardo) 2011-10-24
|
||||
|
||||
Notes:
|
||||
|
||||
--*/
|
||||
#include"tactical.h"
|
||||
#include"aig.h"
|
||||
|
||||
class aig_manager;
|
||||
|
||||
class aig_tactic : public tactic {
|
||||
unsigned long long m_max_memory;
|
||||
bool m_aig_gate_encoding;
|
||||
bool m_aig_per_assertion;
|
||||
aig_manager * m_aig_manager;
|
||||
|
||||
struct mk_aig_manager {
|
||||
aig_tactic & m_owner;
|
||||
|
||||
mk_aig_manager(aig_tactic & o, ast_manager & m):m_owner(o) {
|
||||
aig_manager * mng = alloc(aig_manager, m, o.m_max_memory, o.m_aig_gate_encoding);
|
||||
#pragma omp critical (aig_tactic)
|
||||
{
|
||||
m_owner.m_aig_manager = mng;
|
||||
}
|
||||
}
|
||||
|
||||
~mk_aig_manager() {
|
||||
aig_manager * mng = m_owner.m_aig_manager;
|
||||
#pragma omp critical (aig_tactic)
|
||||
{
|
||||
m_owner.m_aig_manager = 0;
|
||||
}
|
||||
dealloc(mng);
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
aig_tactic(params_ref const & p = params_ref()):m_aig_manager(0) {
|
||||
updt_params(p);
|
||||
}
|
||||
|
||||
virtual tactic * translate(ast_manager & m) {
|
||||
aig_tactic * t = alloc(aig_tactic);
|
||||
t->m_max_memory = m_max_memory;
|
||||
t->m_aig_gate_encoding = m_aig_gate_encoding;
|
||||
t->m_aig_per_assertion = m_aig_per_assertion;
|
||||
return t;
|
||||
}
|
||||
|
||||
virtual void updt_params(params_ref const & p) {
|
||||
m_max_memory = megabytes_to_bytes(p.get_uint(":max-memory", UINT_MAX));
|
||||
m_aig_gate_encoding = p.get_bool(":aig-default-gate-encoding", true);
|
||||
m_aig_per_assertion = p.get_bool(":aig-per-assertion", true);
|
||||
}
|
||||
|
||||
virtual void collect_param_descrs(param_descrs & r) {
|
||||
insert_max_memory(r);
|
||||
r.insert(":aig-per-assertion", CPK_BOOL, "(default: true) process one assertion at a time.");
|
||||
}
|
||||
|
||||
void operator()(goal_ref const & g) {
|
||||
SASSERT(g->is_well_sorted());
|
||||
tactic_report report("aig", *g);
|
||||
|
||||
mk_aig_manager mk(*this, g->m());
|
||||
if (m_aig_per_assertion) {
|
||||
unsigned size = g->size();
|
||||
for (unsigned i = 0; i < size; i++) {
|
||||
aig_ref r = m_aig_manager->mk_aig(g->form(i));
|
||||
m_aig_manager->max_sharing(r);
|
||||
expr_ref new_f(g->m());
|
||||
m_aig_manager->to_formula(r, new_f);
|
||||
g->update(i, new_f, 0, g->dep(i));
|
||||
}
|
||||
}
|
||||
else {
|
||||
fail_if_unsat_core_generation("aig", g);
|
||||
aig_ref r = m_aig_manager->mk_aig(*(g.get()));
|
||||
g->reset(); // save memory
|
||||
m_aig_manager->max_sharing(r);
|
||||
m_aig_manager->to_formula(r, *(g.get()));
|
||||
}
|
||||
SASSERT(g->is_well_sorted());
|
||||
}
|
||||
|
||||
virtual void operator()(goal_ref const & g,
|
||||
goal_ref_buffer & result,
|
||||
model_converter_ref & mc,
|
||||
proof_converter_ref & pc,
|
||||
expr_dependency_ref & core) {
|
||||
fail_if_proof_generation("aig", g);
|
||||
mc = 0; pc = 0; core = 0;
|
||||
operator()(g);
|
||||
g->inc_depth();
|
||||
result.push_back(g.get());
|
||||
}
|
||||
|
||||
virtual void cleanup() {}
|
||||
|
||||
protected:
|
||||
virtual void set_cancel(bool f) {
|
||||
#pragma omp critical (aig_tactic)
|
||||
{
|
||||
if (m_aig_manager)
|
||||
m_aig_manager->set_cancel(f);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
tactic * mk_aig_tactic(params_ref const & p) {
|
||||
return clean(alloc(aig_tactic, p));
|
||||
}
|
27
lib/aig_tactic.h
Normal file
27
lib/aig_tactic.h
Normal file
|
@ -0,0 +1,27 @@
|
|||
/*++
|
||||
Copyright (c) 2011 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
aig_tactic.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Tactic for minimizing circuits using AIGs.
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo (leonardo) 2011-10-24
|
||||
|
||||
Notes:
|
||||
|
||||
--*/
|
||||
#ifndef _AIG_TACTIC_H_
|
||||
#define _AIG_TACTIC_H_
|
||||
|
||||
#include"params.h"
|
||||
class tactic;
|
||||
|
||||
tactic * mk_aig_tactic(params_ref const & p = params_ref());
|
||||
|
||||
#endif
|
3117
lib/algebraic_numbers.cpp
Normal file
3117
lib/algebraic_numbers.cpp
Normal file
File diff suppressed because it is too large
Load diff
493
lib/algebraic_numbers.h
Normal file
493
lib/algebraic_numbers.h
Normal file
|
@ -0,0 +1,493 @@
|
|||
/*++
|
||||
Copyright (c) 2011 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
algebraic_numbers.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Real Algebraic Numbers
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo (leonardo) 2011-11-22
|
||||
|
||||
Notes:
|
||||
|
||||
--*/
|
||||
#ifndef _ALGEBRAIC_NUMBERS_H_
|
||||
#define _ALGEBRAIC_NUMBERS_H_
|
||||
|
||||
#include"rational.h"
|
||||
#include"mpq.h"
|
||||
#include"polynomial.h"
|
||||
#include"z3_exception.h"
|
||||
#include"scoped_numeral.h"
|
||||
#include"scoped_numeral_vector.h"
|
||||
#include"tptr.h"
|
||||
#include"statistics.h"
|
||||
#include"params.h"
|
||||
|
||||
class small_object_allocator;
|
||||
class mpbq_manager;
|
||||
class mpbq;
|
||||
|
||||
namespace algebraic_numbers {
|
||||
class anum;
|
||||
class manager;
|
||||
|
||||
class algebraic_exception : public default_exception {
|
||||
public:
|
||||
algebraic_exception(char const * msg):default_exception(msg) {}
|
||||
};
|
||||
|
||||
class manager {
|
||||
public:
|
||||
struct imp;
|
||||
private:
|
||||
imp * m_imp;
|
||||
small_object_allocator * m_allocator;
|
||||
bool m_own_allocator;
|
||||
public:
|
||||
static bool precise() { return true; }
|
||||
static bool field() { return true; }
|
||||
typedef anum numeral;
|
||||
typedef svector<numeral> numeral_vector;
|
||||
typedef _scoped_numeral<manager> scoped_numeral;
|
||||
typedef _scoped_numeral_vector<manager> scoped_numeral_vector;
|
||||
|
||||
manager(unsynch_mpq_manager & m, params_ref const & p = params_ref(), small_object_allocator * a = 0);
|
||||
~manager();
|
||||
|
||||
static void get_param_descrs(param_descrs & r);
|
||||
static void collect_param_descrs(param_descrs & r) { get_param_descrs(r); }
|
||||
|
||||
void set_cancel(bool f);
|
||||
|
||||
void updt_params(params_ref const & p);
|
||||
|
||||
unsynch_mpq_manager & qm() const;
|
||||
|
||||
mpbq_manager & bqm() const;
|
||||
|
||||
void del(numeral & a);
|
||||
|
||||
/**
|
||||
\brief a <- 0
|
||||
*/
|
||||
void reset(numeral & a);
|
||||
|
||||
/**
|
||||
\brief Return true if a is zero.
|
||||
*/
|
||||
bool is_zero(numeral const & a);
|
||||
|
||||
/**
|
||||
\brief Return true if a is positive.
|
||||
*/
|
||||
bool is_pos(numeral const & a);
|
||||
|
||||
/**
|
||||
\brief Return true if a is negative.
|
||||
*/
|
||||
bool is_neg(numeral const & a);
|
||||
|
||||
/**
|
||||
\brief Return true if a is a rational number.
|
||||
*/
|
||||
bool is_rational(numeral const & a);
|
||||
|
||||
/**
|
||||
\brief Return true if a is an integer.
|
||||
*/
|
||||
bool is_int(numeral const & a);
|
||||
|
||||
/**
|
||||
\brief Degree of the algebraic number.
|
||||
That is, degree of the polynomial that is used to encode \c a.
|
||||
*/
|
||||
unsigned degree(numeral const & a);
|
||||
|
||||
/**
|
||||
\brief Convert a into a rational number.
|
||||
|
||||
\pre is_rational(a)
|
||||
*/
|
||||
void to_rational(numeral const & a, mpq & r);
|
||||
|
||||
/**
|
||||
\brief Convert a into a rational number.
|
||||
|
||||
\pre is_rational(a)
|
||||
*/
|
||||
void to_rational(numeral const & a, rational & r);
|
||||
|
||||
/**
|
||||
\brief a <- n
|
||||
*/
|
||||
void set(numeral & a, int n);
|
||||
void set(numeral & a, mpz const & n);
|
||||
void set(numeral & a, mpq const & n);
|
||||
void set(numeral & a, numeral const & n);
|
||||
|
||||
void swap(numeral & a, numeral & b);
|
||||
|
||||
/**
|
||||
\brief Store in b an integer value smaller than 'a'.
|
||||
|
||||
Remark: this is not the floor, but b <= floor(a)
|
||||
*/
|
||||
void int_lt(numeral const & a, numeral & b);
|
||||
|
||||
/**
|
||||
\brief Store in b an integer value bigger than 'a'
|
||||
|
||||
Remark: this is not the ceil, but b >= ceil(a)
|
||||
*/
|
||||
void int_gt(numeral const & a, numeral & b);
|
||||
|
||||
/**
|
||||
\brief Store in result a value in the interval (prev, next)
|
||||
|
||||
\pre lt(pre,v next)
|
||||
*/
|
||||
void select(numeral const & prev, numeral const & curr, numeral & result);
|
||||
|
||||
/**
|
||||
\brief Isolate the roots of (an univariate polynomial) p, and store them as algebraic numbers in \c root.
|
||||
That is, p is in Z[x].
|
||||
*/
|
||||
void isolate_roots(polynomial_ref const & p, numeral_vector & roots);
|
||||
|
||||
/**
|
||||
\brief Isolate the roots of a multivariate polynomial p such that all but one variable of p is fixed by x2v, and
|
||||
store them as algebraic numbers in \c root.
|
||||
|
||||
That is, we are viewing p as a polynomial in Z[y_1, ..., y_n][x]:
|
||||
q_n(y_1, ..., y_n)x^n + ... + q_1(y_1, ..., y_n)*x + q_0
|
||||
And we are returning the roots of
|
||||
q_n(x2v(y_1), ..., x2v(y_n))x^n + ... + q_1(x2v(y_1), ..., x2v(y_n))*x + q_0
|
||||
*/
|
||||
void isolate_roots(polynomial_ref const & p, polynomial::var2anum const & x2v, numeral_vector & roots);
|
||||
|
||||
/**
|
||||
\brief Isolate the roots of the given polynomial, and compute its sign between them.
|
||||
*/
|
||||
void isolate_roots(polynomial_ref const & p, polynomial::var2anum const & x2v, numeral_vector & roots, svector<int> & signs);
|
||||
|
||||
/**
|
||||
\brief Store in r the i-th root of p.
|
||||
|
||||
This method throws an exception if p does not have at least i roots.
|
||||
|
||||
This method is not really used in the nonlinear procedure.
|
||||
It is mainly used for debugging purposes, and creating regression tests
|
||||
|
||||
\pre i > 0
|
||||
*/
|
||||
void mk_root(polynomial_ref const & p, unsigned i, numeral & r);
|
||||
|
||||
/**
|
||||
\brief Store in r the i-th root of p.
|
||||
This method throws an exception if the s-expression p does not represent
|
||||
an univariate polynomial, of if p does not have at least i roots.
|
||||
|
||||
This method is not really used in the nonlinear procedure.
|
||||
It is mainly used for debugging purposes, and "reading" root objects in the SMT 2.0 front-end.
|
||||
|
||||
\pre i > 0
|
||||
*/
|
||||
void mk_root(sexpr const * p, unsigned i, numeral & r);
|
||||
|
||||
/**
|
||||
\brief Return a^{1/k}
|
||||
|
||||
Throws an exception if the result is not a real.
|
||||
That is, (a is negative and k is even) or (k is zero).
|
||||
*/
|
||||
void root(numeral const & a, unsigned k, numeral & b);
|
||||
|
||||
/**
|
||||
\brief Return a^k
|
||||
|
||||
Throws an exception if 0^0.
|
||||
*/
|
||||
void power(numeral const & a, unsigned k, numeral & b);
|
||||
|
||||
/**
|
||||
\brief c <- a + b
|
||||
*/
|
||||
void add(numeral const & a, numeral const & b, numeral & c);
|
||||
void add(numeral const & a, mpz const & b, numeral & c);
|
||||
|
||||
/**
|
||||
\brief c <- a - b
|
||||
*/
|
||||
void sub(numeral const & a, numeral const & b, numeral & c);
|
||||
|
||||
/**
|
||||
\brief c <- a * b
|
||||
*/
|
||||
void mul(numeral const & a, numeral const & b, numeral & c);
|
||||
|
||||
/**
|
||||
\brief a <- -a
|
||||
*/
|
||||
void neg(numeral & a);
|
||||
|
||||
/**
|
||||
\brief a <- 1/a if a != 0
|
||||
*/
|
||||
void inv(numeral & a);
|
||||
|
||||
/**
|
||||
\brief c <- a/b if b != 0
|
||||
*/
|
||||
void div(numeral const & a, numeral const & b, numeral & c);
|
||||
|
||||
/**
|
||||
Return -1 if a < b
|
||||
Return 0 if a == b
|
||||
Return 1 if a > b
|
||||
*/
|
||||
int compare(numeral const & a, numeral const & b);
|
||||
|
||||
/**
|
||||
\brief a == b
|
||||
*/
|
||||
bool eq(numeral const & a, numeral const & b);
|
||||
bool eq(numeral const & a, mpq const & b);
|
||||
bool eq(numeral const & a, mpz const & b);
|
||||
|
||||
/**
|
||||
\brief a != b
|
||||
*/
|
||||
bool neq(numeral const & a, numeral const & b) { return !eq(a, b); }
|
||||
bool neq(numeral const & a, mpq const & b) { return !eq(a, b); }
|
||||
bool neq(numeral const & a, mpz const & b) { return !eq(a, b); }
|
||||
|
||||
/**
|
||||
\brief a < b
|
||||
*/
|
||||
bool lt(numeral const & a, numeral const & b);
|
||||
bool lt(numeral const & a, mpq const & b);
|
||||
bool lt(numeral const & a, mpz const & b);
|
||||
|
||||
/**
|
||||
\brief a > b
|
||||
*/
|
||||
bool gt(numeral const & a, numeral const & b) { return lt(b, a); }
|
||||
bool gt(numeral const & a, mpq const & b);
|
||||
bool gt(numeral const & a, mpz const & b);
|
||||
|
||||
/**
|
||||
\brief a <= b
|
||||
*/
|
||||
bool le(numeral const & a, numeral const & b) { return !gt(a, b); }
|
||||
bool le(numeral const & a, mpq const & b) { return !gt(a, b); }
|
||||
bool le(numeral const & a, mpz const & b) { return !gt(a, b); }
|
||||
|
||||
/**
|
||||
\brief a >= b
|
||||
*/
|
||||
bool ge(numeral const & a, numeral const & b) { return !lt(a, b); }
|
||||
bool ge(numeral const & a, mpq const & b) { return !lt(a, b); }
|
||||
bool ge(numeral const & a, mpz const & b) { return !lt(a, b); }
|
||||
|
||||
/**
|
||||
\brief Evaluate the sign of a multivariate polynomial p(x_1, ..., x_n)
|
||||
at assignment x2v: [x_1 -> alpha_1, ..., x_n -> alpha_n].
|
||||
|
||||
\remark forall variable x in p, we have that x2v.contains(x) is true
|
||||
|
||||
Return negative number if p(alpha_1, ..., alpha_n) < 0
|
||||
Return 0 if p(alpha_1, ..., alpha_n) == 0
|
||||
Return positive number if p(alpha_1, ..., alpha_n) > 0
|
||||
*/
|
||||
int eval_sign_at(polynomial_ref const & p, polynomial::var2anum const & x2v);
|
||||
|
||||
void get_polynomial(numeral const & a, svector<mpz> & r);
|
||||
|
||||
// Procedures for getting lower and upper bounds for irrational numbers
|
||||
void get_lower(numeral const & a, mpbq & l);
|
||||
void get_lower(numeral const & a, mpq & l);
|
||||
void get_lower(numeral const & a, rational & l);
|
||||
void get_lower(numeral const & a, mpq & l, unsigned precision);
|
||||
void get_lower(numeral const & a, rational & l, unsigned precision);
|
||||
|
||||
void get_upper(numeral const & a, mpbq & u);
|
||||
void get_upper(numeral const & a, mpq & u);
|
||||
void get_upper(numeral const & a, rational & u);
|
||||
void get_upper(numeral const & a, mpq & l, unsigned precision);
|
||||
void get_upper(numeral const & a, rational & l, unsigned precision);
|
||||
|
||||
/**
|
||||
\brief Display algebraic number as a rational if is_rational(n)
|
||||
Otherwise, display it as an interval.
|
||||
*/
|
||||
void display_interval(std::ostream & out, numeral const & a) const;
|
||||
|
||||
/**
|
||||
\brief Display algebraic number in decimal notation.
|
||||
A question mark is added based on the precision requested.
|
||||
*/
|
||||
void display_decimal(std::ostream & out, numeral const & a, unsigned precision = 10) const;
|
||||
|
||||
/**
|
||||
\brief Display algebraic number as a root object: (p, i)
|
||||
That is, 'a' is the i-th root of p.
|
||||
*/
|
||||
void display_root(std::ostream & out, numeral const & a) const;
|
||||
|
||||
/**
|
||||
\brief Display algebraic number as a root object in SMT 2.0 style: (root-obj p i)
|
||||
That is, 'a' is the i-th root of p.
|
||||
*/
|
||||
void display_root_smt2(std::ostream & out, numeral const & a) const;
|
||||
|
||||
/**
|
||||
\brief Display algebraic number in Mathematica format.
|
||||
*/
|
||||
void display_mathematica(std::ostream & out, numeral const & a) const;
|
||||
|
||||
void display(std::ostream & out, numeral const & a) { return display_decimal(out, a); }
|
||||
|
||||
void reset_statistics();
|
||||
|
||||
void collect_statistics(statistics & st) const;
|
||||
};
|
||||
|
||||
struct basic_cell;
|
||||
struct algebraic_cell;
|
||||
|
||||
enum anum_kind { BASIC = 0, ROOT };
|
||||
|
||||
class anum {
|
||||
friend struct manager::imp;
|
||||
friend class manager;
|
||||
void * m_cell;
|
||||
anum(basic_cell * cell):m_cell(TAG(void*, cell, BASIC)) {}
|
||||
anum(algebraic_cell * cell):m_cell(TAG(void*, cell, ROOT)) {}
|
||||
bool is_basic() const { return GET_TAG(m_cell) == BASIC; }
|
||||
basic_cell * to_basic() const { SASSERT(is_basic()); return UNTAG(basic_cell*, m_cell); }
|
||||
algebraic_cell * to_algebraic() const { SASSERT(!is_basic()); return UNTAG(algebraic_cell*, m_cell); }
|
||||
public:
|
||||
anum():m_cell(0) {}
|
||||
};
|
||||
};
|
||||
|
||||
typedef algebraic_numbers::manager anum_manager;
|
||||
typedef algebraic_numbers::manager::numeral anum;
|
||||
typedef algebraic_numbers::manager::numeral_vector anum_vector;
|
||||
typedef algebraic_numbers::manager::scoped_numeral scoped_anum;
|
||||
typedef algebraic_numbers::manager::scoped_numeral_vector scoped_anum_vector;
|
||||
|
||||
#define AN_MK_COMPARISON_CORE(EXTERNAL, INTERNAL, TYPE) \
|
||||
inline bool EXTERNAL(scoped_anum const & a, TYPE const & b) { \
|
||||
anum_manager & m = a.m(); \
|
||||
scoped_anum _b(m); \
|
||||
m.set(_b, b); \
|
||||
return m.INTERNAL(a, _b); \
|
||||
}
|
||||
|
||||
#define AN_MK_COMPARISON(EXTERNAL, INTERNAL) \
|
||||
AN_MK_COMPARISON_CORE(EXTERNAL, INTERNAL, int) \
|
||||
AN_MK_COMPARISON_CORE(EXTERNAL, INTERNAL, mpz) \
|
||||
AN_MK_COMPARISON_CORE(EXTERNAL, INTERNAL, mpq)
|
||||
|
||||
AN_MK_COMPARISON(operator==, eq);
|
||||
AN_MK_COMPARISON(operator!=, neq);
|
||||
AN_MK_COMPARISON(operator<, lt);
|
||||
AN_MK_COMPARISON(operator<=, le);
|
||||
AN_MK_COMPARISON(operator>, gt);
|
||||
AN_MK_COMPARISON(operator>=, ge);
|
||||
|
||||
#undef AN_MK_COMPARISON
|
||||
#undef AN_MK_COMPARISON_CORE
|
||||
|
||||
#define AN_MK_BINARY_CORE(EXTERNAL, INTERNAL, TYPE) \
|
||||
inline scoped_anum EXTERNAL(scoped_anum const & a, TYPE const & b) { \
|
||||
anum_manager & m = a.m(); \
|
||||
scoped_anum _b(m); \
|
||||
m.set(_b, b); \
|
||||
scoped_anum r(m); \
|
||||
m.INTERNAL(a, _b, r); \
|
||||
return r; \
|
||||
}
|
||||
|
||||
#define AN_MK_BINARY(EXTERNAL, INTERNAL) \
|
||||
AN_MK_BINARY_CORE(EXTERNAL, INTERNAL, int) \
|
||||
AN_MK_BINARY_CORE(EXTERNAL, INTERNAL, mpz) \
|
||||
AN_MK_BINARY_CORE(EXTERNAL, INTERNAL, mpq)
|
||||
|
||||
AN_MK_BINARY(operator+, add)
|
||||
AN_MK_BINARY(operator-, sub)
|
||||
AN_MK_BINARY(operator*, mul)
|
||||
AN_MK_BINARY(operator/, div)
|
||||
|
||||
#undef AN_MK_BINARY
|
||||
#undef AN_MK_BINARY_CORE
|
||||
|
||||
inline scoped_anum root(scoped_anum const & a, unsigned k) {
|
||||
scoped_anum r(a.m());
|
||||
a.m().root(a, k, r);
|
||||
return r;
|
||||
}
|
||||
|
||||
inline scoped_anum power(scoped_anum const & a, unsigned k) {
|
||||
scoped_anum r(a.m());
|
||||
a.m().power(a, k, r);
|
||||
return r;
|
||||
}
|
||||
|
||||
inline scoped_anum operator^(scoped_anum const & a, unsigned k) {
|
||||
return power(a, k);
|
||||
}
|
||||
|
||||
inline bool is_int(scoped_anum const & a) {
|
||||
return a.m().is_int(a);
|
||||
}
|
||||
|
||||
inline bool is_rational(scoped_anum const & a) {
|
||||
return a.m().is_rational(a);
|
||||
}
|
||||
|
||||
struct root_obj_pp {
|
||||
anum_manager & m;
|
||||
anum const & n;
|
||||
root_obj_pp(anum_manager & _m, anum const & _n):m(_m), n(_n) {}
|
||||
root_obj_pp(scoped_anum const & _n):m(_n.m()), n(_n.get()) {}
|
||||
};
|
||||
|
||||
inline std::ostream & operator<<(std::ostream & out, root_obj_pp const & n) {
|
||||
n.m.display_root(out, n.n);
|
||||
return out;
|
||||
}
|
||||
|
||||
struct decimal_pp {
|
||||
anum_manager & m;
|
||||
anum const & n;
|
||||
unsigned prec;
|
||||
decimal_pp(anum_manager & _m, anum const & _n, unsigned p):m(_m), n(_n), prec(p) {}
|
||||
decimal_pp(scoped_anum const & _n, unsigned p):m(_n.m()), n(_n.get()), prec(p) {}
|
||||
};
|
||||
|
||||
inline std::ostream & operator<<(std::ostream & out, decimal_pp const & n) {
|
||||
n.m.display_decimal(out, n.n, n.prec);
|
||||
return out;
|
||||
}
|
||||
|
||||
struct interval_pp {
|
||||
anum_manager & m;
|
||||
anum const & n;
|
||||
interval_pp(anum_manager & _m, anum const & _n):m(_m), n(_n) {}
|
||||
interval_pp(scoped_anum const & _n):m(_n.m()), n(_n.get()) {}
|
||||
};
|
||||
|
||||
inline std::ostream & operator<<(std::ostream & out, interval_pp const & n) {
|
||||
n.m.display_interval(out, n.n);
|
||||
return out;
|
||||
}
|
||||
|
||||
#endif
|
1236
lib/api.py
Normal file
1236
lib/api.py
Normal file
File diff suppressed because it is too large
Load diff
219
lib/api_arith.cpp
Normal file
219
lib/api_arith.cpp
Normal file
|
@ -0,0 +1,219 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
api_arith.cpp
|
||||
|
||||
Abstract:
|
||||
API for arith theory
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2012-02-29.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include<iostream>
|
||||
#include"z3.h"
|
||||
#include"api_log_macros.h"
|
||||
#include"api_context.h"
|
||||
#include"api_util.h"
|
||||
#include"arith_decl_plugin.h"
|
||||
#include"algebraic_numbers.h"
|
||||
|
||||
#define MK_ARITH_OP(NAME, OP) MK_NARY(NAME, mk_c(c)->get_arith_fid(), OP, SKIP)
|
||||
#define MK_BINARY_ARITH_OP(NAME, OP) MK_BINARY(NAME, mk_c(c)->get_arith_fid(), OP, SKIP)
|
||||
#define MK_ARITH_PRED(NAME, OP) MK_BINARY(NAME, mk_c(c)->get_arith_fid(), OP, SKIP)
|
||||
|
||||
extern "C" {
|
||||
|
||||
Z3_sort Z3_API Z3_mk_int_sort(Z3_context c) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_int_sort(c);
|
||||
RESET_ERROR_CODE();
|
||||
Z3_sort r = of_sort(mk_c(c)->m().mk_sort(mk_c(c)->get_arith_fid(), INT_SORT));
|
||||
RETURN_Z3(r);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_sort Z3_API Z3_mk_real_sort(Z3_context c) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_real_sort(c);
|
||||
RESET_ERROR_CODE();
|
||||
Z3_sort r = of_sort(mk_c(c)->m().mk_sort(mk_c(c)->get_arith_fid(), REAL_SORT));
|
||||
RETURN_Z3(r);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_mk_real(__in Z3_context c, int num, int den) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_real(c, num, den);
|
||||
RESET_ERROR_CODE();
|
||||
if (den == 0) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
sort* s = mk_c(c)->m().mk_sort(mk_c(c)->get_arith_fid(), REAL_SORT);
|
||||
ast* a = mk_c(c)->mk_numeral_core(rational(num, den), s);
|
||||
RETURN_Z3(of_ast(a));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
MK_ARITH_OP(Z3_mk_add, OP_ADD);
|
||||
MK_ARITH_OP(Z3_mk_mul, OP_MUL);
|
||||
MK_BINARY_ARITH_OP(Z3_mk_power, OP_POWER);
|
||||
MK_BINARY_ARITH_OP(Z3_mk_mod, OP_MOD);
|
||||
MK_BINARY_ARITH_OP(Z3_mk_rem, OP_REM);
|
||||
|
||||
Z3_ast Z3_API Z3_mk_div(Z3_context c, Z3_ast n1, Z3_ast n2) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_div(c, n1, n2);
|
||||
RESET_ERROR_CODE();
|
||||
decl_kind k = OP_IDIV;
|
||||
sort* ty = mk_c(c)->m().get_sort(to_expr(n1));
|
||||
sort* real_ty = mk_c(c)->m().mk_sort(mk_c(c)->get_arith_fid(), REAL_SORT);
|
||||
if (ty == real_ty) {
|
||||
k = OP_DIV;
|
||||
}
|
||||
expr * args[2] = { to_expr(n1), to_expr(n2) };
|
||||
ast* a = mk_c(c)->m().mk_app(mk_c(c)->get_arith_fid(), k, 0, 0, 2, args);
|
||||
mk_c(c)->save_ast_trail(a);
|
||||
check_sorts(c, a);
|
||||
RETURN_Z3(of_ast(a));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
MK_ARITH_PRED(Z3_mk_lt, OP_LT);
|
||||
MK_ARITH_PRED(Z3_mk_gt, OP_GT);
|
||||
MK_ARITH_PRED(Z3_mk_le, OP_LE);
|
||||
MK_ARITH_PRED(Z3_mk_ge, OP_GE);
|
||||
MK_UNARY(Z3_mk_int2real, mk_c(c)->get_arith_fid(), OP_TO_REAL, SKIP);
|
||||
MK_UNARY(Z3_mk_real2int, mk_c(c)->get_arith_fid(), OP_TO_INT, SKIP);
|
||||
MK_UNARY(Z3_mk_is_int, mk_c(c)->get_arith_fid(), OP_IS_INT, SKIP);
|
||||
|
||||
Z3_ast Z3_API Z3_mk_sub(Z3_context c, unsigned num_args, Z3_ast const args[]) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_sub(c, num_args, args);
|
||||
RESET_ERROR_CODE();
|
||||
if (num_args == 0) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
if (mk_c(c)->fparams().m_pre_simplify_expr) {
|
||||
// Do not use logging here... the function is implemented using API primitives
|
||||
Z3_ast m1 = Z3_mk_int(c, -1, Z3_get_sort(c, args[0]));
|
||||
Z3_ast args1[2] = { args[0], 0 };
|
||||
for (unsigned i = 1; i < num_args; ++i) {
|
||||
Z3_ast args2[3] = { m1, args[i] };
|
||||
args1[1] = Z3_mk_mul(c, 2, args2);
|
||||
args1[0] = Z3_mk_add(c, 2, args1);
|
||||
}
|
||||
RETURN_Z3(args1[0]);
|
||||
}
|
||||
else {
|
||||
expr* r = to_expr(args[0]);
|
||||
for (unsigned i = 1; i < num_args; ++i) {
|
||||
expr* args1[2] = { r, to_expr(args[i]) };
|
||||
r = mk_c(c)->m().mk_app(mk_c(c)->get_arith_fid(), OP_SUB, 0, 0, 2, args1);
|
||||
check_sorts(c, r);
|
||||
}
|
||||
mk_c(c)->save_ast_trail(r);
|
||||
RETURN_Z3(of_expr(r));
|
||||
}
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_mk_unary_minus(Z3_context c, Z3_ast n) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_unary_minus(c, n);
|
||||
RESET_ERROR_CODE();
|
||||
if (mk_c(c)->fparams().m_pre_simplify_expr) {
|
||||
Z3_ast m1 = Z3_mk_int(c, -1, Z3_get_sort(c, n));
|
||||
Z3_ast args[2] = { m1, n };
|
||||
Z3_ast r = Z3_mk_mul(c, 2, args);
|
||||
RETURN_Z3(r);
|
||||
}
|
||||
MK_UNARY_BODY(Z3_mk_unary_minus, mk_c(c)->get_arith_fid(), OP_UMINUS, SKIP);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_bool Z3_API Z3_is_algebraic_number(Z3_context c, Z3_ast a) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_is_algebraic_number(c, a);
|
||||
RESET_ERROR_CODE();
|
||||
expr * e = to_expr(a);
|
||||
return mk_c(c)->autil().is_irrational_algebraic_numeral(e);
|
||||
Z3_CATCH_RETURN(Z3_FALSE);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_get_algebraic_number_lower(Z3_context c, Z3_ast a, unsigned precision) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_algebraic_number_lower(c, a, precision);
|
||||
RESET_ERROR_CODE();
|
||||
if (!Z3_is_algebraic_number(c, a)) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
expr * e = to_expr(a);
|
||||
algebraic_numbers::anum const & val = mk_c(c)->autil().to_irrational_algebraic_numeral(e);
|
||||
rational l;
|
||||
mk_c(c)->autil().am().get_lower(val, l, precision);
|
||||
expr * r = mk_c(c)->autil().mk_numeral(l, false);
|
||||
mk_c(c)->save_ast_trail(r);
|
||||
RETURN_Z3(of_expr(r));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_get_algebraic_number_upper(Z3_context c, Z3_ast a, unsigned precision) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_algebraic_number_upper(c, a, precision);
|
||||
RESET_ERROR_CODE();
|
||||
if (!Z3_is_algebraic_number(c, a)) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
expr * e = to_expr(a);
|
||||
algebraic_numbers::anum const & val = mk_c(c)->autil().to_irrational_algebraic_numeral(e);
|
||||
rational l;
|
||||
mk_c(c)->autil().am().get_upper(val, l, precision);
|
||||
expr * r = mk_c(c)->autil().mk_numeral(l, false);
|
||||
mk_c(c)->save_ast_trail(r);
|
||||
RETURN_Z3(of_expr(r));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_get_numerator(Z3_context c, Z3_ast a) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_numerator(c, a);
|
||||
RESET_ERROR_CODE();
|
||||
rational val;
|
||||
ast * _a = to_ast(a);
|
||||
if (!is_expr(_a) || !mk_c(c)->autil().is_numeral(to_expr(_a), val)) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
expr * r = mk_c(c)->autil().mk_numeral(numerator(val), true);
|
||||
mk_c(c)->save_ast_trail(r);
|
||||
RETURN_Z3(of_expr(r));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_get_denominator(Z3_context c, Z3_ast a) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_denominator(c, a);
|
||||
RESET_ERROR_CODE();
|
||||
rational val;
|
||||
ast * _a = to_ast(a);
|
||||
if (!is_expr(_a) || !mk_c(c)->autil().is_numeral(to_expr(_a), val)) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
expr * r = mk_c(c)->autil().mk_numeral(denominator(val), true);
|
||||
mk_c(c)->save_ast_trail(r);
|
||||
RETURN_Z3(of_expr(r));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
};
|
233
lib/api_array.cpp
Normal file
233
lib/api_array.cpp
Normal file
|
@ -0,0 +1,233 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
api_array.cpp
|
||||
|
||||
Abstract:
|
||||
API for array theory
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2012-02-29.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include<iostream>
|
||||
#include"z3.h"
|
||||
#include"api_log_macros.h"
|
||||
#include"api_context.h"
|
||||
#include"api_util.h"
|
||||
#include"array_decl_plugin.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
Z3_sort Z3_API Z3_mk_array_sort(Z3_context c, Z3_sort domain, Z3_sort range) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_array_sort(c, domain, range);
|
||||
RESET_ERROR_CODE();
|
||||
parameter params[2] = { parameter(to_sort(domain)), parameter(to_sort(range)) };
|
||||
sort * ty = mk_c(c)->m().mk_sort(mk_c(c)->get_array_fid(), ARRAY_SORT, 2, params);
|
||||
mk_c(c)->save_ast_trail(ty);
|
||||
RETURN_Z3(of_sort(ty));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_mk_select(Z3_context c, Z3_ast a, Z3_ast i) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_select(c, a, i);
|
||||
RESET_ERROR_CODE();
|
||||
ast_manager & m = mk_c(c)->m();
|
||||
expr * _a = to_expr(a);
|
||||
expr * _i = to_expr(i);
|
||||
sort * a_ty = m.get_sort(_a);
|
||||
sort * i_ty = m.get_sort(_i);
|
||||
if (a_ty->get_family_id() != mk_c(c)->get_array_fid()) {
|
||||
SET_ERROR_CODE(Z3_SORT_ERROR);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
sort * domain[2] = {a_ty, i_ty};
|
||||
func_decl * d = m.mk_func_decl(mk_c(c)->get_array_fid(), OP_SELECT, 2, a_ty->get_parameters(), 2, domain);
|
||||
expr * args[2] = {_a, _i};
|
||||
app * r = m.mk_app(d, 2, args);
|
||||
mk_c(c)->save_ast_trail(r);
|
||||
check_sorts(c, r);
|
||||
RETURN_Z3(of_ast(r));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_mk_store(Z3_context c, Z3_ast a, Z3_ast i, Z3_ast v) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_store(c, a, i, v);
|
||||
RESET_ERROR_CODE();
|
||||
ast_manager & m = mk_c(c)->m();
|
||||
expr * _a = to_expr(a);
|
||||
expr * _i = to_expr(i);
|
||||
expr * _v = to_expr(v);
|
||||
sort * a_ty = m.get_sort(_a);
|
||||
sort * i_ty = m.get_sort(_i);
|
||||
sort * v_ty = m.get_sort(_v);
|
||||
if (a_ty->get_family_id() != mk_c(c)->get_array_fid()) {
|
||||
SET_ERROR_CODE(Z3_SORT_ERROR);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
sort * domain[3] = {a_ty, i_ty, v_ty};
|
||||
func_decl * d = m.mk_func_decl(mk_c(c)->get_array_fid(), OP_STORE, 2, a_ty->get_parameters(), 3, domain);
|
||||
expr * args[3] = {_a, _i, _v};
|
||||
app * r = m.mk_app(d, 3, args);
|
||||
mk_c(c)->save_ast_trail(r);
|
||||
check_sorts(c, r);
|
||||
RETURN_Z3(of_ast(r));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_mk_map(__in Z3_context c, __in Z3_func_decl f, unsigned n, __in Z3_ast const* args) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_map(c, f, n, args);
|
||||
RESET_ERROR_CODE();
|
||||
if (n == 0) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
ast_manager & m = mk_c(c)->m();
|
||||
func_decl* _f = to_func_decl(f);
|
||||
expr* const* _args = to_exprs(args);
|
||||
|
||||
ptr_vector<sort> domain;
|
||||
for (unsigned i = 0; i < n; ++i) {
|
||||
domain.push_back(m.get_sort(_args[i]));
|
||||
}
|
||||
parameter param(_f);
|
||||
func_decl * d = m.mk_func_decl(mk_c(c)->get_array_fid(), OP_ARRAY_MAP, 1, ¶m, n, domain.c_ptr());
|
||||
app* r = m.mk_app(d, n, _args);
|
||||
mk_c(c)->save_ast_trail(r);
|
||||
check_sorts(c, r);
|
||||
RETURN_Z3(of_ast(r));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_mk_const_array(__in Z3_context c, __in Z3_sort domain, __in Z3_ast v) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_const_array(c, domain, v);
|
||||
RESET_ERROR_CODE();
|
||||
ast_manager & m = mk_c(c)->m();
|
||||
expr * _v = to_expr(v);
|
||||
sort * _range = m.get_sort(_v);
|
||||
sort * _domain = to_sort(domain);
|
||||
parameter params[2] = { parameter(_domain), parameter(_range) };
|
||||
sort * a_ty = mk_c(c)->m().mk_sort(mk_c(c)->get_array_fid(), ARRAY_SORT, 2, params);
|
||||
parameter param(a_ty);
|
||||
func_decl* cd = m.mk_func_decl(mk_c(c)->get_array_fid(), OP_CONST_ARRAY, 1, ¶m, 1, &_range);
|
||||
app * r = m.mk_app(cd, 1, &_v);
|
||||
mk_c(c)->save_ast_trail(r);
|
||||
check_sorts(c, r);
|
||||
RETURN_Z3(of_ast(r));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_mk_array_default(__in Z3_context c, __in Z3_ast array) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_array_default(c, array);
|
||||
RESET_ERROR_CODE();
|
||||
ast_manager & m = mk_c(c)->m();
|
||||
expr * _a = to_expr(array);
|
||||
|
||||
func_decl * f = m.mk_func_decl(mk_c(c)->get_array_fid(), OP_ARRAY_DEFAULT, 0, 0, 1, &_a);
|
||||
app * r = m.mk_app(f, 1, &_a);
|
||||
mk_c(c)->save_ast_trail(r);
|
||||
check_sorts(c, r);
|
||||
RETURN_Z3(of_ast(r));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast mk_app_array_core(__in Z3_context c, __in Z3_sort domain, __in Z3_ast v) {
|
||||
RESET_ERROR_CODE();
|
||||
ast_manager & m = mk_c(c)->m();
|
||||
expr * _v = to_expr(v);
|
||||
sort * _range = m.get_sort(_v);
|
||||
sort * _domain = to_sort(domain);
|
||||
parameter params[2] = { parameter(_domain), parameter(_range) };
|
||||
sort * a_ty = mk_c(c)->m().mk_sort(mk_c(c)->get_array_fid(), ARRAY_SORT, 2, params);
|
||||
parameter param(a_ty);
|
||||
func_decl * cd = m.mk_func_decl(mk_c(c)->get_array_fid(), OP_CONST_ARRAY, 1, ¶m, 1, &_range);
|
||||
app * r = m.mk_app(cd, 1, &_v);
|
||||
mk_c(c)->save_ast_trail(r);
|
||||
check_sorts(c, r);
|
||||
return of_ast(r);
|
||||
}
|
||||
|
||||
Z3_sort Z3_API Z3_mk_set_sort(__in Z3_context c, __in Z3_sort ty) {
|
||||
Z3_TRY;
|
||||
return Z3_mk_array_sort(c, ty, Z3_mk_bool_sort(c));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_mk_empty_set(__in Z3_context c, __in Z3_sort domain) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_empty_set(c, domain);
|
||||
RESET_ERROR_CODE();
|
||||
Z3_ast r = mk_app_array_core(c, domain, Z3_mk_false(c));
|
||||
RETURN_Z3(r);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_mk_full_set(__in Z3_context c, __in Z3_sort domain) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_full_set(c, domain);
|
||||
RESET_ERROR_CODE();
|
||||
Z3_ast r = mk_app_array_core(c, domain, Z3_mk_true(c));
|
||||
RETURN_Z3(r);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
MK_NARY(Z3_mk_set_union, mk_c(c)->get_array_fid(), OP_SET_UNION, SKIP);
|
||||
MK_NARY(Z3_mk_set_intersect, mk_c(c)->get_array_fid(), OP_SET_INTERSECT, SKIP);
|
||||
MK_BINARY(Z3_mk_set_difference, mk_c(c)->get_array_fid(), OP_SET_DIFFERENCE, SKIP);
|
||||
MK_UNARY(Z3_mk_set_complement, mk_c(c)->get_array_fid(), OP_SET_COMPLEMENT, SKIP);
|
||||
MK_BINARY(Z3_mk_set_subset, mk_c(c)->get_array_fid(), OP_SET_SUBSET, SKIP);
|
||||
|
||||
Z3_ast Z3_mk_set_member(__in Z3_context c, __in Z3_ast elem, __in Z3_ast set) {
|
||||
return Z3_mk_select(c, set, elem);
|
||||
}
|
||||
|
||||
Z3_ast Z3_mk_set_add(__in Z3_context c, __in Z3_ast set, __in Z3_ast elem) {
|
||||
return Z3_mk_store(c, set, elem, Z3_mk_true(c));
|
||||
}
|
||||
|
||||
Z3_ast Z3_mk_set_del(__in Z3_context c, __in Z3_ast set, __in Z3_ast elem) {
|
||||
return Z3_mk_store(c, set, elem, Z3_mk_false(c));
|
||||
}
|
||||
|
||||
Z3_sort Z3_API Z3_get_array_sort_domain(Z3_context c, Z3_sort t) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_array_sort_domain(c, t);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_VALID_AST(t, 0);
|
||||
if (to_sort(t)->get_family_id() == mk_c(c)->get_array_fid() &&
|
||||
to_sort(t)->get_decl_kind() == ARRAY_SORT) {
|
||||
Z3_sort r = reinterpret_cast<Z3_sort>(to_sort(t)->get_parameter(0).get_ast());
|
||||
RETURN_Z3(r);
|
||||
}
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_sort Z3_API Z3_get_array_sort_range(Z3_context c, Z3_sort t) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_array_sort_range(c, t);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_VALID_AST(t, 0);
|
||||
if (to_sort(t)->get_family_id() == mk_c(c)->get_array_fid() &&
|
||||
to_sort(t)->get_decl_kind() == ARRAY_SORT) {
|
||||
Z3_sort r = reinterpret_cast<Z3_sort>(to_sort(t)->get_parameter(1).get_ast());
|
||||
RETURN_Z3(r);
|
||||
}
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
};
|
1156
lib/api_ast.cpp
Normal file
1156
lib/api_ast.cpp
Normal file
File diff suppressed because it is too large
Load diff
169
lib/api_ast_map.cpp
Normal file
169
lib/api_ast_map.cpp
Normal file
|
@ -0,0 +1,169 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
api_ast_map.cpp
|
||||
|
||||
Abstract:
|
||||
API for creating AST maps
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2012-03-09.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include<iostream>
|
||||
#include"z3.h"
|
||||
#include"api_log_macros.h"
|
||||
#include"api_context.h"
|
||||
#include"api_ast_map.h"
|
||||
#include"api_ast_vector.h"
|
||||
#include"ast_smt2_pp.h"
|
||||
#include"dec_ref_util.h"
|
||||
|
||||
Z3_ast_map_ref::~Z3_ast_map_ref() {
|
||||
dec_ref_key_values(m, m_map);
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
Z3_ast_map Z3_API Z3_mk_ast_map(Z3_context c) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_ast_map(c);
|
||||
RESET_ERROR_CODE();
|
||||
Z3_ast_map_ref * m = alloc(Z3_ast_map_ref, mk_c(c)->m());
|
||||
mk_c(c)->save_object(m);
|
||||
Z3_ast_map r = of_ast_map(m);
|
||||
RETURN_Z3(r);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
void Z3_API Z3_ast_map_inc_ref(Z3_context c, Z3_ast_map m) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_ast_map_inc_ref(c, m);
|
||||
RESET_ERROR_CODE();
|
||||
to_ast_map(m)->inc_ref();
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_ast_map_dec_ref(Z3_context c, Z3_ast_map m) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_ast_map_dec_ref(c, m);
|
||||
RESET_ERROR_CODE();
|
||||
to_ast_map(m)->dec_ref();
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
Z3_bool Z3_API Z3_ast_map_contains(Z3_context c, Z3_ast_map m, Z3_ast k) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_ast_map_contains(c, m, k);
|
||||
RESET_ERROR_CODE();
|
||||
return to_ast_map_ref(m).contains(to_ast(k));
|
||||
Z3_CATCH_RETURN(Z3_FALSE);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_ast_map_find(Z3_context c, Z3_ast_map m, Z3_ast k) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_ast_map_find(c, m, k);
|
||||
RESET_ERROR_CODE();
|
||||
obj_map<ast, ast*>::obj_map_entry * entry = to_ast_map_ref(m).find_core(to_ast(k));
|
||||
if (entry == 0) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
else {
|
||||
ast * r = entry->get_data().m_value;
|
||||
RETURN_Z3(of_ast(r));
|
||||
}
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
void Z3_API Z3_ast_map_insert(Z3_context c, Z3_ast_map m, Z3_ast k, Z3_ast v) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_ast_map_insert(c, m, k, v);
|
||||
RESET_ERROR_CODE();
|
||||
ast_manager & mng = to_ast_map(m)->m;
|
||||
obj_map<ast, ast*>::obj_map_entry * entry = to_ast_map_ref(m).insert_if_not_there2(to_ast(k), 0);
|
||||
if (entry->get_data().m_value == 0) {
|
||||
// new entry
|
||||
mng.inc_ref(to_ast(k));
|
||||
mng.inc_ref(to_ast(v));
|
||||
entry->get_data().m_value = to_ast(v);
|
||||
}
|
||||
else {
|
||||
// replacing entry
|
||||
mng.inc_ref(to_ast(v));
|
||||
mng.dec_ref(entry->get_data().m_value);
|
||||
entry->get_data().m_value = to_ast(v);
|
||||
}
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_ast_map_reset(Z3_context c, Z3_ast_map m) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_ast_map_reset(c, m);
|
||||
RESET_ERROR_CODE();
|
||||
dec_ref_key_values(to_ast_map(m)->m, to_ast_map_ref(m));
|
||||
SASSERT(to_ast_map_ref(m).empty());
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_ast_map_erase(Z3_context c, Z3_ast_map m, Z3_ast k) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_ast_map_erase(c, m, k);
|
||||
RESET_ERROR_CODE();
|
||||
ast * v = 0;
|
||||
if (to_ast_map_ref(m).find(to_ast(k), v)) {
|
||||
to_ast_map_ref(m).erase(to_ast(k));
|
||||
ast_manager & mng = to_ast_map(m)->m;
|
||||
mng.dec_ref(to_ast(k));
|
||||
mng.dec_ref(v);
|
||||
}
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
unsigned Z3_API Z3_ast_map_size(Z3_context c, Z3_ast_map m) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_ast_map_size(c, m);
|
||||
RESET_ERROR_CODE();
|
||||
return to_ast_map_ref(m).size();
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast_vector Z3_API Z3_ast_map_keys(Z3_context c, Z3_ast_map m) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_ast_map_keys(c, m);
|
||||
RESET_ERROR_CODE();
|
||||
Z3_ast_vector_ref * v = alloc(Z3_ast_vector_ref, to_ast_map(m)->m);
|
||||
mk_c(c)->save_object(v);
|
||||
obj_map<ast, ast*>::iterator it = to_ast_map_ref(m).begin();
|
||||
obj_map<ast, ast*>::iterator end = to_ast_map_ref(m).end();
|
||||
for (; it != end; ++it) {
|
||||
v->m_ast_vector.push_back(it->m_key);
|
||||
}
|
||||
Z3_ast_vector r = of_ast_vector(v);
|
||||
RETURN_Z3(r);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_string Z3_API Z3_ast_map_to_string(Z3_context c, Z3_ast_map m) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_ast_map_to_string(c, m);
|
||||
RESET_ERROR_CODE();
|
||||
std::ostringstream buffer;
|
||||
ast_manager & mng = to_ast_map(m)->m;
|
||||
buffer << "(ast-map";
|
||||
obj_map<ast, ast*>::iterator it = to_ast_map_ref(m).begin();
|
||||
obj_map<ast, ast*>::iterator end = to_ast_map_ref(m).end();
|
||||
for (; it != end; ++it) {
|
||||
buffer << "\n (" << mk_ismt2_pp(it->m_key, mng, 3) << "\n " << mk_ismt2_pp(it->m_value, mng, 3) << ")";
|
||||
}
|
||||
buffer << ")";
|
||||
return mk_c(c)->mk_external_string(buffer.str());
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
};
|
35
lib/api_ast_map.h
Normal file
35
lib/api_ast_map.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
api_ast_map.h
|
||||
|
||||
Abstract:
|
||||
API for creating AST maps
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2012-03-09.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _API_AST_MAP_H_
|
||||
#define _API_AST_MAP_H_
|
||||
|
||||
#include"api_util.h"
|
||||
#include"obj_hashtable.h"
|
||||
|
||||
struct Z3_ast_map_ref : public api::object {
|
||||
ast_manager & m;
|
||||
obj_map<ast, ast*> m_map;
|
||||
Z3_ast_map_ref(ast_manager & _m):m(_m) {}
|
||||
virtual ~Z3_ast_map_ref();
|
||||
};
|
||||
|
||||
inline Z3_ast_map_ref * to_ast_map(Z3_ast_map v) { return reinterpret_cast<Z3_ast_map_ref *>(v); }
|
||||
inline Z3_ast_map of_ast_map(Z3_ast_map_ref * v) { return reinterpret_cast<Z3_ast_map>(v); }
|
||||
inline obj_map<ast, ast*> & to_ast_map_ref(Z3_ast_map v) { return to_ast_map(v)->m_map; }
|
||||
|
||||
#endif
|
140
lib/api_ast_vector.cpp
Normal file
140
lib/api_ast_vector.cpp
Normal file
|
@ -0,0 +1,140 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
api_ast_vector.cpp
|
||||
|
||||
Abstract:
|
||||
API for creating AST vectors
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2012-03-09.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include<iostream>
|
||||
#include"z3.h"
|
||||
#include"api_log_macros.h"
|
||||
#include"api_context.h"
|
||||
#include"api_ast_vector.h"
|
||||
#include"ast_translation.h"
|
||||
#include"ast_smt2_pp.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
Z3_ast_vector Z3_API Z3_mk_ast_vector(Z3_context c) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_ast_vector(c);
|
||||
RESET_ERROR_CODE();
|
||||
Z3_ast_vector_ref * v = alloc(Z3_ast_vector_ref, mk_c(c)->m());
|
||||
mk_c(c)->save_object(v);
|
||||
Z3_ast_vector r = of_ast_vector(v);
|
||||
RETURN_Z3(r);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
void Z3_API Z3_ast_vector_inc_ref(Z3_context c, Z3_ast_vector v) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_ast_vector_inc_ref(c, v);
|
||||
RESET_ERROR_CODE();
|
||||
to_ast_vector(v)->inc_ref();
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_ast_vector_dec_ref(Z3_context c, Z3_ast_vector v) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_ast_vector_dec_ref(c, v);
|
||||
RESET_ERROR_CODE();
|
||||
to_ast_vector(v)->dec_ref();
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
unsigned Z3_API Z3_ast_vector_size(Z3_context c, Z3_ast_vector v) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_ast_vector_size(c, v);
|
||||
RESET_ERROR_CODE();
|
||||
return to_ast_vector_ref(v).size();
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_ast_vector_get(Z3_context c, Z3_ast_vector v, unsigned i) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_ast_vector_get(c, v, i);
|
||||
RESET_ERROR_CODE();
|
||||
if (i >= to_ast_vector_ref(v).size()) {
|
||||
SET_ERROR_CODE(Z3_IOB);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
// Remark: Don't need to invoke save_object.
|
||||
ast * r = to_ast_vector_ref(v).get(i);
|
||||
RETURN_Z3(of_ast(r));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
void Z3_API Z3_ast_vector_set(Z3_context c, Z3_ast_vector v, unsigned i, Z3_ast a) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_ast_vector_set(c, v, i, a);
|
||||
RESET_ERROR_CODE();
|
||||
if (i >= to_ast_vector_ref(v).size()) {
|
||||
SET_ERROR_CODE(Z3_IOB);
|
||||
return;
|
||||
}
|
||||
to_ast_vector_ref(v).set(i, to_ast(a));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_ast_vector_resize(Z3_context c, Z3_ast_vector v, unsigned n) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_ast_vector_resize(c, v, n);
|
||||
RESET_ERROR_CODE();
|
||||
to_ast_vector_ref(v).resize(n);
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_ast_vector_push(Z3_context c, Z3_ast_vector v, Z3_ast a) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_ast_vector_push(c, v, a);
|
||||
RESET_ERROR_CODE();
|
||||
to_ast_vector_ref(v).push_back(to_ast(a));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
Z3_ast_vector Z3_API Z3_ast_vector_translate(Z3_context c, Z3_ast_vector v, Z3_context t) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_ast_vector_translate(c, v, t);
|
||||
RESET_ERROR_CODE();
|
||||
if (c == t) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
ast_translation translator(mk_c(c)->m(), mk_c(t)->m());
|
||||
Z3_ast_vector_ref * new_v = alloc(Z3_ast_vector_ref, mk_c(t)->m());
|
||||
mk_c(t)->save_object(new_v);
|
||||
unsigned sz = to_ast_vector_ref(v).size();
|
||||
for (unsigned i = 0; i < sz; i++) {
|
||||
ast * new_ast = translator(to_ast_vector_ref(v).get(i));
|
||||
new_v->m_ast_vector.push_back(new_ast);
|
||||
}
|
||||
RETURN_Z3(of_ast_vector(new_v));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_string Z3_API Z3_ast_vector_to_string(Z3_context c, Z3_ast_vector v) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_ast_vector_to_string(c, v);
|
||||
RESET_ERROR_CODE();
|
||||
std::ostringstream buffer;
|
||||
buffer << "(ast-vector";
|
||||
unsigned sz = to_ast_vector_ref(v).size();
|
||||
for (unsigned i = 0; i < sz; i++) {
|
||||
buffer << "\n " << mk_ismt2_pp(to_ast_vector_ref(v).get(i), mk_c(c)->m(), 2);
|
||||
}
|
||||
buffer << ")";
|
||||
return mk_c(c)->mk_external_string(buffer.str());
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
};
|
33
lib/api_ast_vector.h
Normal file
33
lib/api_ast_vector.h
Normal file
|
@ -0,0 +1,33 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
api_ast_vector.h
|
||||
|
||||
Abstract:
|
||||
API for creating AST vectors
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2012-03-09.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _API_AST_VECTOR_H_
|
||||
#define _API_AST_VECTOR_H_
|
||||
|
||||
#include"api_util.h"
|
||||
|
||||
struct Z3_ast_vector_ref : public api::object {
|
||||
ast_ref_vector m_ast_vector;
|
||||
Z3_ast_vector_ref(ast_manager & m):m_ast_vector(m) {}
|
||||
virtual ~Z3_ast_vector_ref() {}
|
||||
};
|
||||
|
||||
inline Z3_ast_vector_ref * to_ast_vector(Z3_ast_vector v) { return reinterpret_cast<Z3_ast_vector_ref *>(v); }
|
||||
inline Z3_ast_vector of_ast_vector(Z3_ast_vector_ref * v) { return reinterpret_cast<Z3_ast_vector>(v); }
|
||||
inline ast_ref_vector & to_ast_vector_ref(Z3_ast_vector v) { return to_ast_vector(v)->m_ast_vector; }
|
||||
|
||||
#endif
|
320
lib/api_bv.cpp
Normal file
320
lib/api_bv.cpp
Normal file
|
@ -0,0 +1,320 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
api_bv.cpp
|
||||
|
||||
Abstract:
|
||||
API for bv theory
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2012-02-29.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include<iostream>
|
||||
#include"z3.h"
|
||||
#include"api_log_macros.h"
|
||||
#include"api_context.h"
|
||||
#include"api_util.h"
|
||||
#include"bv_decl_plugin.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
Z3_sort Z3_API Z3_mk_bv_sort(Z3_context c, unsigned sz) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_bv_sort(c, sz);
|
||||
RESET_ERROR_CODE();
|
||||
if (sz == 0) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
}
|
||||
parameter p(sz);
|
||||
Z3_sort r = of_sort(mk_c(c)->m().mk_sort(mk_c(c)->get_bv_fid(), BV_SORT, 1, &p));
|
||||
RETURN_Z3(r);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
#define MK_BV_UNARY(NAME, OP) MK_UNARY(NAME, mk_c(c)->get_bv_fid(), OP, SKIP)
|
||||
#define MK_BV_BINARY(NAME, OP) MK_BINARY(NAME, mk_c(c)->get_bv_fid(), OP, SKIP)
|
||||
|
||||
MK_BV_UNARY(Z3_mk_bvnot, OP_BNOT);
|
||||
MK_BV_UNARY(Z3_mk_bvredand, OP_BREDAND);
|
||||
MK_BV_UNARY(Z3_mk_bvredor, OP_BREDOR);
|
||||
MK_BV_BINARY(Z3_mk_bvand, OP_BAND);
|
||||
MK_BV_BINARY(Z3_mk_bvor, OP_BOR);
|
||||
MK_BV_BINARY(Z3_mk_bvxor, OP_BXOR);
|
||||
MK_BV_BINARY(Z3_mk_bvnand, OP_BNAND);
|
||||
MK_BV_BINARY(Z3_mk_bvnor, OP_BNOR);
|
||||
MK_BV_BINARY(Z3_mk_bvxnor, OP_BXNOR);
|
||||
MK_BV_BINARY(Z3_mk_bvadd, OP_BADD);
|
||||
MK_BV_BINARY(Z3_mk_bvmul, OP_BMUL);
|
||||
MK_BV_BINARY(Z3_mk_bvudiv, OP_BUDIV);
|
||||
MK_BV_BINARY(Z3_mk_bvsdiv, OP_BSDIV);
|
||||
MK_BV_BINARY(Z3_mk_bvurem, OP_BUREM);
|
||||
MK_BV_BINARY(Z3_mk_bvsrem, OP_BSREM);
|
||||
MK_BV_BINARY(Z3_mk_bvsmod, OP_BSMOD);
|
||||
MK_BV_BINARY(Z3_mk_bvule, OP_ULEQ);
|
||||
MK_BV_BINARY(Z3_mk_bvsle, OP_SLEQ);
|
||||
MK_BV_BINARY(Z3_mk_bvuge, OP_UGEQ);
|
||||
MK_BV_BINARY(Z3_mk_bvsge, OP_SGEQ);
|
||||
MK_BV_BINARY(Z3_mk_bvult, OP_ULT);
|
||||
MK_BV_BINARY(Z3_mk_bvslt, OP_SLT);
|
||||
MK_BV_BINARY(Z3_mk_bvugt, OP_UGT);
|
||||
MK_BV_BINARY(Z3_mk_bvsgt, OP_SGT);
|
||||
MK_BV_BINARY(Z3_mk_concat, OP_CONCAT);
|
||||
MK_BV_BINARY(Z3_mk_bvshl, OP_BSHL);
|
||||
MK_BV_BINARY(Z3_mk_bvlshr, OP_BLSHR);
|
||||
MK_BV_BINARY(Z3_mk_bvashr, OP_BASHR);
|
||||
MK_BV_BINARY(Z3_mk_ext_rotate_left, OP_EXT_ROTATE_LEFT);
|
||||
MK_BV_BINARY(Z3_mk_ext_rotate_right, OP_EXT_ROTATE_RIGHT);
|
||||
|
||||
Z3_ast mk_extract_core(Z3_context c, unsigned high, unsigned low, Z3_ast n) {
|
||||
expr * _n = to_expr(n);
|
||||
parameter params[2] = { parameter(high), parameter(low) };
|
||||
expr * a = mk_c(c)->m().mk_app(mk_c(c)->get_bv_fid(), OP_EXTRACT, 2, params, 1, &_n);
|
||||
mk_c(c)->save_ast_trail(a);
|
||||
check_sorts(c, a);
|
||||
return of_ast(a);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_mk_extract(Z3_context c, unsigned high, unsigned low, Z3_ast n) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_extract(c, high, low, n);
|
||||
RESET_ERROR_CODE();
|
||||
Z3_ast r = mk_extract_core(c, high, low, n);
|
||||
RETURN_Z3(r);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
#define MK_BV_PUNARY(NAME, OP) \
|
||||
Z3_ast Z3_API NAME(Z3_context c, unsigned i, Z3_ast n) { \
|
||||
Z3_TRY; \
|
||||
LOG_ ## NAME(c, i, n); \
|
||||
RESET_ERROR_CODE(); \
|
||||
expr * _n = to_expr(n); \
|
||||
parameter p(i); \
|
||||
ast* a = mk_c(c)->m().mk_app(mk_c(c)->get_bv_fid(), OP, 1, &p, 1, &_n); \
|
||||
mk_c(c)->save_ast_trail(a); \
|
||||
check_sorts(c, a); \
|
||||
RETURN_Z3(of_ast(a)); \
|
||||
Z3_CATCH_RETURN(0); \
|
||||
}
|
||||
|
||||
MK_BV_PUNARY(Z3_mk_sign_ext, OP_SIGN_EXT);
|
||||
MK_BV_PUNARY(Z3_mk_zero_ext, OP_ZERO_EXT);
|
||||
MK_BV_PUNARY(Z3_mk_repeat, OP_REPEAT);
|
||||
MK_BV_PUNARY(Z3_mk_rotate_left, OP_ROTATE_LEFT);
|
||||
MK_BV_PUNARY(Z3_mk_rotate_right, OP_ROTATE_RIGHT);
|
||||
MK_BV_PUNARY(Z3_mk_int2bv, OP_INT2BV);
|
||||
|
||||
Z3_ast Z3_API Z3_mk_bv2int(Z3_context c, Z3_ast n, Z3_bool is_signed) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_bv2int(c, n, is_signed);
|
||||
RESET_ERROR_CODE();
|
||||
Z3_sort int_s = Z3_mk_int_sort(c);
|
||||
if (is_signed) {
|
||||
Z3_ast r = Z3_mk_bv2int(c, n, false);
|
||||
Z3_sort s = Z3_get_sort(c, n);
|
||||
unsigned sz = Z3_get_bv_sort_size(c, s);
|
||||
rational max_bound = power(rational(2), sz);
|
||||
Z3_ast bound = Z3_mk_numeral(c, max_bound.to_string().c_str(), int_s);
|
||||
Z3_ast pred = Z3_mk_bvslt(c, n, Z3_mk_int(c, 0, s));
|
||||
// if n <_sigend 0 then r - s^sz else r
|
||||
Z3_ast args[2] = { r, bound };
|
||||
Z3_ast res = Z3_mk_ite(c, pred, Z3_mk_sub(c, 2, args), r);
|
||||
RETURN_Z3(res);
|
||||
}
|
||||
else {
|
||||
expr * _n = to_expr(n);
|
||||
parameter p(to_sort(int_s));
|
||||
ast* a = mk_c(c)->m().mk_app(mk_c(c)->get_bv_fid(), OP_BV2INT, 1, &p, 1, &_n);
|
||||
mk_c(c)->save_ast_trail(a);
|
||||
check_sorts(c, a);
|
||||
RETURN_Z3(of_ast(a));
|
||||
}
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
/**
|
||||
\brief \mlh mk_bvmsb c s \endmlh
|
||||
Create a bit-vector of sort \s with 1 in the most significant bit position.
|
||||
|
||||
The sort \s must be a bit-vector sort.
|
||||
|
||||
This function is a shorthand for <tt>shl(1, N-1)</tt>
|
||||
where <tt>N</tt> are the number of bits of \c s.
|
||||
*/
|
||||
Z3_ast Z3_API Z3_mk_bvmsb(__in Z3_context c, __in Z3_sort s) {
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
// Not logging this one, since it is just syntax sugar.
|
||||
unsigned sz = Z3_get_bv_sort_size(c, s);
|
||||
if (sz == 0) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
return 0;
|
||||
}
|
||||
return Z3_mk_bvshl(c, Z3_mk_int64(c, 1, s), Z3_mk_int64(c, sz - 1, s));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_mk_bvsmin(__in Z3_context c, __in Z3_sort s) {
|
||||
return Z3_mk_bvmsb(c, s);
|
||||
}
|
||||
|
||||
Z3_ast Z3_mk_bvsmax(__in Z3_context c, __in Z3_sort s) {
|
||||
return Z3_mk_bvnot(c, Z3_mk_bvmsb(c, s));
|
||||
}
|
||||
|
||||
Z3_ast Z3_mk_bvumax(__in Z3_context c, __in Z3_sort s) {
|
||||
return Z3_mk_int(c, -1, s);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_mk_bvadd_no_overflow(__in Z3_context c, __in Z3_ast t1, __in Z3_ast t2, Z3_bool is_signed) {
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
if (is_signed) {
|
||||
Z3_ast zero = Z3_mk_int(c, 0, Z3_get_sort(c, t1));
|
||||
Z3_ast r = Z3_mk_bvadd(c, t1, t2);
|
||||
Z3_ast args[2] = { Z3_mk_bvslt(c, zero, t1), Z3_mk_bvslt(c, zero, t2) };
|
||||
Z3_ast args_pos = Z3_mk_and(c, 2, args);
|
||||
return Z3_mk_implies(c, args_pos, Z3_mk_bvslt(c, zero, r));
|
||||
}
|
||||
else {
|
||||
unsigned sz = Z3_get_bv_sort_size(c, Z3_get_sort(c, t1));
|
||||
t1 = Z3_mk_zero_ext(c, 1, t1);
|
||||
t2 = Z3_mk_zero_ext(c, 1, t2);
|
||||
Z3_ast r = Z3_mk_bvadd(c, t1, t2);
|
||||
return Z3_mk_eq(c, Z3_mk_extract(c, sz, sz, r), Z3_mk_int(c, 0, Z3_mk_bv_sort(c, 1)));
|
||||
}
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
// only for signed machine integers
|
||||
Z3_ast Z3_API Z3_mk_bvadd_no_underflow(__in Z3_context c, __in Z3_ast t1, __in Z3_ast t2) {
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
Z3_ast zero = Z3_mk_int(c, 0, Z3_get_sort(c, t1));
|
||||
Z3_ast r = Z3_mk_bvadd(c, t1, t2);
|
||||
Z3_ast args[2] = { Z3_mk_bvslt(c, t1, zero), Z3_mk_bvslt(c, t2, zero) };
|
||||
Z3_ast args_neg = Z3_mk_and(c, 2, args);
|
||||
return Z3_mk_implies(c, args_neg, Z3_mk_bvslt(c, r, zero));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
// only for signed machine integers
|
||||
Z3_ast Z3_API Z3_mk_bvsub_no_overflow(__in Z3_context c, __in Z3_ast t1, __in Z3_ast t2) {
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
Z3_sort s = Z3_get_sort(c, t2);
|
||||
Z3_ast minus_t2 = Z3_mk_bvneg(c, t2);
|
||||
Z3_ast min = Z3_mk_bvsmin(c, s);
|
||||
return Z3_mk_ite(c, Z3_mk_eq(c, t2, min),
|
||||
Z3_mk_bvslt(c, t1, Z3_mk_int(c, 0, s)),
|
||||
Z3_mk_bvadd_no_overflow(c, t1, minus_t2, true));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_mk_bvsub_no_underflow(__in Z3_context c, __in Z3_ast t1, __in Z3_ast t2, Z3_bool is_signed) {
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
if (is_signed) {
|
||||
Z3_ast zero = Z3_mk_int(c, 0, Z3_get_sort(c, t1));
|
||||
if (Z3_get_error_code(c) != Z3_OK) return 0;
|
||||
Z3_ast minus_t2 = Z3_mk_bvneg(c, t2);
|
||||
if (Z3_get_error_code(c) != Z3_OK) return 0;
|
||||
return Z3_mk_implies(c, Z3_mk_bvslt(c, zero, t2), Z3_mk_bvadd_no_underflow(c, t1, minus_t2));
|
||||
}
|
||||
else {
|
||||
return Z3_mk_bvule(c, t2, t1);
|
||||
}
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_mk_bvmul_no_overflow(__in Z3_context c, __in Z3_ast n1, __in Z3_ast n2, Z3_bool is_signed) {
|
||||
LOG_Z3_mk_bvmul_no_overflow(c, n1, n2, is_signed);
|
||||
RESET_ERROR_CODE();
|
||||
if (is_signed) {
|
||||
MK_BINARY_BODY(Z3_mk_bvmul_no_overflow, mk_c(c)->get_bv_fid(), OP_BSMUL_NO_OVFL, SKIP);
|
||||
}
|
||||
else {
|
||||
MK_BINARY_BODY(Z3_mk_bvmul_no_overflow, mk_c(c)->get_bv_fid(), OP_BUMUL_NO_OVFL, SKIP);
|
||||
}
|
||||
}
|
||||
|
||||
// only for signed machine integers
|
||||
Z3_ast Z3_API Z3_mk_bvmul_no_underflow(__in Z3_context c, __in Z3_ast n1, __in Z3_ast n2) {
|
||||
LOG_Z3_mk_bvmul_no_underflow(c, n1, n2);
|
||||
MK_BINARY_BODY(Z3_mk_bvmul_no_underflow, mk_c(c)->get_bv_fid(), OP_BSMUL_NO_UDFL, SKIP);
|
||||
}
|
||||
|
||||
// only for signed machine integers
|
||||
Z3_ast Z3_API Z3_mk_bvneg_no_overflow(__in Z3_context c, __in Z3_ast t) {
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
Z3_ast min = Z3_mk_bvsmin(c, Z3_get_sort(c, t));
|
||||
if (Z3_get_error_code(c) != Z3_OK) return 0;
|
||||
Z3_ast eq = Z3_mk_eq(c, t, min);
|
||||
if (Z3_get_error_code(c) != Z3_OK) return 0;
|
||||
return Z3_mk_not(c, eq);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
// only for signed machine integers
|
||||
Z3_ast Z3_API Z3_mk_bvsdiv_no_overflow(__in Z3_context c, __in Z3_ast t1, __in Z3_ast t2) {
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
Z3_sort s = Z3_get_sort(c, t1);
|
||||
if (Z3_get_error_code(c) != Z3_OK) return 0;
|
||||
Z3_ast min = Z3_mk_bvmsb(c, s);
|
||||
if (Z3_get_error_code(c) != Z3_OK) return 0;
|
||||
Z3_ast args[2] = { Z3_mk_eq(c, t1, min),
|
||||
Z3_mk_eq(c, t2, Z3_mk_int(c, -1, s)) };
|
||||
return Z3_mk_not(c, Z3_mk_and(c, 2, args));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_mk_bvsub(Z3_context c, Z3_ast n1, Z3_ast n2) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_bvsub(c, n1, n2);
|
||||
RESET_ERROR_CODE();
|
||||
// TODO: Do we really need this pre_simplifier hack?
|
||||
if (mk_c(c)->fparams().m_pre_simplify_expr) {
|
||||
Z3_ast m1 = Z3_mk_int(c, -1, Z3_get_sort(c, n2));
|
||||
Z3_ast r = Z3_mk_bvadd(c, n1, Z3_mk_bvmul(c, m1, n2));
|
||||
RETURN_Z3(r);
|
||||
}
|
||||
MK_BINARY_BODY(Z3_mk_bvsub, mk_c(c)->get_bv_fid(), OP_BSUB, SKIP);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_mk_bvneg(Z3_context c, Z3_ast n) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_bvneg(c, n);
|
||||
RESET_ERROR_CODE();
|
||||
// TODO: Do we really need this pre_simplifier hack?
|
||||
if (mk_c(c)->fparams().m_pre_simplify_expr) {
|
||||
Z3_ast m1 = Z3_mk_int(c, -1, Z3_get_sort(c, n));
|
||||
Z3_ast r = Z3_mk_bvmul(c, m1, n);
|
||||
RETURN_Z3(r);
|
||||
}
|
||||
MK_UNARY_BODY(Z3_mk_bvneg, mk_c(c)->get_bv_fid(), OP_BNEG, SKIP);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
unsigned Z3_API Z3_get_bv_sort_size(Z3_context c, Z3_sort t) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_bv_sort_size(c, t);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_VALID_AST(t, 0);
|
||||
if (to_sort(t)->get_family_id() == mk_c(c)->get_bv_fid() && to_sort(t)->get_decl_kind() == BV_SORT) {
|
||||
return to_sort(t)->get_parameter(0).get_int();
|
||||
}
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
return 0;
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
};
|
3478
lib/api_commands.cpp
Normal file
3478
lib/api_commands.cpp
Normal file
File diff suppressed because it is too large
Load diff
122
lib/api_config_params.cpp
Normal file
122
lib/api_config_params.cpp
Normal file
|
@ -0,0 +1,122 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
api_config_params.cpp
|
||||
|
||||
Abstract:
|
||||
Configuration parameters
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2012-02-29.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include"z3.h"
|
||||
#include"api_context.h"
|
||||
#include"api_config_params.h"
|
||||
#include"pp.h"
|
||||
#include"api_log_macros.h"
|
||||
#include"api_util.h"
|
||||
#include"symbol.h"
|
||||
|
||||
namespace api {
|
||||
|
||||
config_params::config_params():
|
||||
m_ini(false /* do not abort on errors */) {
|
||||
register_verbosity_level(m_ini);
|
||||
register_warning(m_ini);
|
||||
m_params.register_params(m_ini);
|
||||
register_pp_params(m_ini);
|
||||
}
|
||||
|
||||
config_params::config_params(front_end_params const & p):m_params(p) {
|
||||
register_verbosity_level(m_ini);
|
||||
register_warning(m_ini);
|
||||
register_pp_params(m_ini);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
extern std::string smt_keyword2opt_name(symbol const & opt);
|
||||
|
||||
extern "C" {
|
||||
Z3_config Z3_API Z3_mk_config() {
|
||||
LOG_Z3_mk_config();
|
||||
memory::initialize(0);
|
||||
Z3_config r = reinterpret_cast<Z3_config>(alloc(api::config_params));
|
||||
RETURN_Z3(r);
|
||||
}
|
||||
|
||||
void Z3_API Z3_del_config(Z3_config c) {
|
||||
LOG_Z3_del_config(c);
|
||||
dealloc((reinterpret_cast<api::config_params*>(c)));
|
||||
}
|
||||
|
||||
void Z3_API Z3_set_param_value(Z3_config c, char const * param_id, char const * param_value) {
|
||||
try {
|
||||
LOG_Z3_set_param_value(c, param_id, param_value);
|
||||
api::config_params* p = reinterpret_cast<api::config_params*>(c);
|
||||
if (param_id != 0 && param_id[0] == ':') {
|
||||
// Allow SMT2 style paramater names such as :model, :relevancy, etc
|
||||
std::string new_param_id = smt_keyword2opt_name(symbol(param_id));
|
||||
p->m_ini.set_param_value(new_param_id.c_str(), param_value);
|
||||
}
|
||||
else {
|
||||
p->m_ini.set_param_value(param_id, param_value);
|
||||
}
|
||||
}
|
||||
catch (set_get_param_exception & ex) {
|
||||
// The error handler was not set yet.
|
||||
// Just throw a warning.
|
||||
std::ostringstream buffer;
|
||||
buffer << "Error setting " << param_id << ", " << ex.get_msg();
|
||||
warning_msg(buffer.str().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void Z3_API Z3_update_param_value(Z3_context c, Z3_string param_id, Z3_string param_value) {
|
||||
LOG_Z3_update_param_value(c, param_id, param_value);
|
||||
RESET_ERROR_CODE();
|
||||
ini_params ini;
|
||||
mk_c(c)->fparams().register_params(ini);
|
||||
register_pp_params(ini);
|
||||
register_verbosity_level(ini);
|
||||
register_warning(ini);
|
||||
if (mk_c(c)->has_solver()) {
|
||||
ini.freeze();
|
||||
}
|
||||
if (param_id != 0 && param_id[0] == ':') {
|
||||
// Allow SMT2 style paramater names such as :model, :relevancy, etc
|
||||
std::string new_param_id = smt_keyword2opt_name(symbol(param_id));
|
||||
ini.set_param_value(new_param_id.c_str(), param_value);
|
||||
}
|
||||
else {
|
||||
ini.set_param_value(param_id, param_value);
|
||||
}
|
||||
memory::set_high_watermark(static_cast<size_t>(mk_c(c)->fparams().m_memory_high_watermark)*1024*1024);
|
||||
memory::set_max_size(static_cast<size_t>(mk_c(c)->fparams().m_memory_max_size)*1024*1024);
|
||||
}
|
||||
|
||||
Z3_bool Z3_API Z3_get_param_value(Z3_context c, Z3_string param_id, Z3_string* param_value) {
|
||||
LOG_Z3_get_param_value(c, param_id, param_value);
|
||||
ini_params ini;
|
||||
mk_c(c)->fparams().register_params(ini);
|
||||
register_verbosity_level(ini);
|
||||
register_pp_params(ini);
|
||||
register_warning(ini);
|
||||
std::string param_value_s;
|
||||
if (!ini.get_param_value(param_id, param_value_s)) {
|
||||
if (param_value) *param_value = 0;
|
||||
return false;
|
||||
}
|
||||
if (param_value) {
|
||||
*param_value = mk_c(c)->mk_external_string(param_value_s);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
};
|
36
lib/api_config_params.h
Normal file
36
lib/api_config_params.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
api_config_params.h
|
||||
|
||||
Abstract:
|
||||
Configuration parameters
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2012-02-29.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _API_CONFIG_PARAMS_H_
|
||||
#define _API_CONFIG_PARAMS_H_
|
||||
|
||||
#include"ini_file.h"
|
||||
#include"front_end_params.h"
|
||||
|
||||
namespace api {
|
||||
|
||||
class config_params {
|
||||
public:
|
||||
ini_params m_ini;
|
||||
front_end_params m_params;
|
||||
config_params();
|
||||
config_params(front_end_params const & p);
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif
|
571
lib/api_context.cpp
Normal file
571
lib/api_context.cpp
Normal file
|
@ -0,0 +1,571 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
api_context.cpp
|
||||
|
||||
Abstract:
|
||||
Interface of Z3 with "external world".
|
||||
|
||||
It was called _Z3_context
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2012-02-29.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include"api_context.h"
|
||||
#include"api_config_params.h"
|
||||
#include"smtparser.h"
|
||||
#include"version.h"
|
||||
#include"ast_pp.h"
|
||||
#include"ast_ll_pp.h"
|
||||
#include"api_log_macros.h"
|
||||
#include"api_util.h"
|
||||
#include"install_tactics.h"
|
||||
|
||||
namespace api {
|
||||
|
||||
static void default_error_handler(Z3_context, Z3_error_code c) {
|
||||
printf("Error: %s\n", Z3_get_error_msg(c));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
Z3_search_failure mk_Z3_search_failure(smt::failure f) {
|
||||
switch(f) {
|
||||
case smt::OK: return Z3_NO_FAILURE;
|
||||
case smt::UNKNOWN: return Z3_UNKNOWN;
|
||||
case smt::TIMEOUT: return Z3_TIMEOUT;
|
||||
case smt::MEMOUT: return Z3_MEMOUT_WATERMARK;
|
||||
case smt::CANCELED: return Z3_CANCELED;
|
||||
case smt::NUM_CONFLICTS: return Z3_NUM_CONFLICTS;
|
||||
case smt::THEORY: return Z3_THEORY;
|
||||
case smt::QUANTIFIERS: return Z3_QUANTIFIERS;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
return static_cast<Z3_search_failure>(f);
|
||||
}
|
||||
|
||||
context::param_ini::param_ini(front_end_params & p) : m_params(p) {
|
||||
p.open_trace_file();
|
||||
}
|
||||
|
||||
context::param_ini::~param_ini() {
|
||||
m_params.close_trace_file();
|
||||
}
|
||||
|
||||
context::add_plugins::add_plugins(ast_manager & m) {
|
||||
m.register_decl_plugins();
|
||||
}
|
||||
|
||||
// ------------------------
|
||||
//
|
||||
// Core
|
||||
//
|
||||
// ------------------------
|
||||
|
||||
context::set_interruptable::set_interruptable(context & ctx, event_handler & i):
|
||||
m_ctx(ctx) {
|
||||
#pragma omp critical (set_interruptable)
|
||||
{
|
||||
SASSERT(m_ctx.m_interruptable == 0);
|
||||
m_ctx.m_interruptable = &i;
|
||||
}
|
||||
}
|
||||
|
||||
context::set_interruptable::~set_interruptable() {
|
||||
#pragma omp critical (set_interruptable)
|
||||
{
|
||||
m_ctx.m_interruptable = 0;
|
||||
}
|
||||
}
|
||||
|
||||
context::context(config_params * p, bool user_ref_count):
|
||||
m_params(p ? p->m_params : front_end_params()),
|
||||
m_param_ini(m_params),
|
||||
m_user_ref_count(user_ref_count),
|
||||
m_manager(m_params.m_proof_mode, m_params.m_trace_stream),
|
||||
m_plugins(m_manager),
|
||||
m_arith_util(m_manager),
|
||||
m_bv_util(m_manager),
|
||||
m_datalog_util(m_manager),
|
||||
m_last_result(m_manager),
|
||||
m_ast_trail(m_manager),
|
||||
m_replay_stack() {
|
||||
|
||||
m_solver = 0;
|
||||
m_error_code = Z3_OK;
|
||||
m_print_mode = Z3_PRINT_SMTLIB_FULL;
|
||||
m_searching = false;
|
||||
|
||||
m_interruptable = 0;
|
||||
|
||||
m_smtlib_parser = 0;
|
||||
m_smtlib_parser_has_decls = false;
|
||||
|
||||
z3_bound_num_procs();
|
||||
//
|
||||
// Configuration parameter settings.
|
||||
//
|
||||
memory::set_high_watermark(static_cast<size_t>(m_params.m_memory_high_watermark)*1024*1024);
|
||||
memory::set_max_size(static_cast<size_t>(m_params.m_memory_max_size)*1024*1024);
|
||||
if (m_params.m_debug_ref_count) {
|
||||
m_manager.debug_ref_count();
|
||||
}
|
||||
|
||||
m_error_handler = &default_error_handler;
|
||||
|
||||
m_basic_fid = m_manager.get_basic_family_id();
|
||||
m_arith_fid = m_manager.get_family_id("arith");
|
||||
m_bv_fid = m_manager.get_family_id("bv");
|
||||
m_array_fid = m_manager.get_family_id("array");
|
||||
m_dt_fid = m_manager.get_family_id("datatype");
|
||||
m_datalog_fid = m_manager.get_family_id("datalog_relation");
|
||||
m_dt_plugin = static_cast<datatype_decl_plugin*>(m_manager.get_plugin(m_dt_fid));
|
||||
|
||||
if (!m_user_ref_count) {
|
||||
m_replay_stack.push_back(0);
|
||||
}
|
||||
|
||||
install_tactics(*this);
|
||||
}
|
||||
|
||||
|
||||
context::~context() {
|
||||
m_last_obj = 0;
|
||||
if (!m_user_ref_count) {
|
||||
for (unsigned i = 0; i < m_replay_stack.size(); ++i) {
|
||||
dealloc(m_replay_stack[i]);
|
||||
}
|
||||
}
|
||||
reset_parser();
|
||||
dealloc(m_solver);
|
||||
}
|
||||
|
||||
void context::interrupt() {
|
||||
#pragma omp critical (set_interruptable)
|
||||
{
|
||||
if (m_interruptable)
|
||||
(*m_interruptable)();
|
||||
}
|
||||
}
|
||||
|
||||
void context::set_error_code(Z3_error_code err) {
|
||||
m_error_code = err;
|
||||
if (err != Z3_OK)
|
||||
invoke_error_handler(err);
|
||||
}
|
||||
|
||||
void context::check_searching() {
|
||||
if (m_searching) {
|
||||
set_error_code(Z3_INVALID_USAGE); // TBD: error code could be fixed.
|
||||
}
|
||||
}
|
||||
|
||||
char * context::mk_external_string(char const * str) {
|
||||
m_string_buffer = str;
|
||||
return const_cast<char *>(m_string_buffer.c_str());
|
||||
}
|
||||
|
||||
char * context::mk_external_string(std::string const & str) {
|
||||
m_string_buffer = str;
|
||||
return const_cast<char *>(m_string_buffer.c_str());
|
||||
}
|
||||
|
||||
expr * context::mk_numeral_core(rational const & n, sort * s) {
|
||||
expr* e = 0;
|
||||
family_id fid = s->get_family_id();
|
||||
if (fid == m_arith_fid) {
|
||||
e = m_arith_util.mk_numeral(n, s);
|
||||
}
|
||||
else if (fid == m_bv_fid) {
|
||||
e = m_bv_util.mk_numeral(n, s);
|
||||
}
|
||||
else if (fid == get_datalog_fid() && n.is_uint64()) {
|
||||
uint64 sz;
|
||||
if (m_datalog_util.try_get_size(s, sz) &&
|
||||
sz <= n.get_uint64()) {
|
||||
invoke_error_handler(Z3_INVALID_ARG);
|
||||
}
|
||||
e = m_datalog_util.mk_numeral(n.get_uint64(), s);
|
||||
}
|
||||
else {
|
||||
invoke_error_handler(Z3_INVALID_ARG);
|
||||
}
|
||||
save_ast_trail(e);
|
||||
return e;
|
||||
}
|
||||
|
||||
expr * context::mk_and(unsigned num_exprs, expr * const * exprs) {
|
||||
switch(num_exprs) {
|
||||
case 0:
|
||||
return m_manager.mk_true();
|
||||
case 1:
|
||||
save_ast_trail(exprs[0]);
|
||||
return exprs[0];
|
||||
default: {
|
||||
expr * a = m_manager.mk_and(num_exprs, exprs);
|
||||
save_ast_trail(a);
|
||||
return a;
|
||||
} }
|
||||
}
|
||||
|
||||
void context::persist_ast(ast * n, unsigned num_scopes) {
|
||||
// persist_ast is irrelevant when m_user_ref_count == true
|
||||
if (m_user_ref_count)
|
||||
return;
|
||||
if (num_scopes > m_ast_lim.size()) {
|
||||
num_scopes = m_ast_lim.size();
|
||||
}
|
||||
SASSERT(m_replay_stack.size() > num_scopes);
|
||||
unsigned j = m_replay_stack.size() - num_scopes - 1;
|
||||
if (!m_replay_stack[j]) {
|
||||
m_replay_stack[j] = alloc(ast_ref_vector, m_manager);
|
||||
}
|
||||
m_replay_stack[j]->push_back(n);
|
||||
}
|
||||
|
||||
void context::save_ast_trail(ast * n) {
|
||||
SASSERT(m().contains(n));
|
||||
if (m_user_ref_count) {
|
||||
// Corner case bug: n may be in m_last_result, and this is the only reference to n.
|
||||
// When, we execute reset() it is deleted
|
||||
// To avoid this bug, I bump the reference counter before reseting m_last_result
|
||||
m().inc_ref(n);
|
||||
m_last_result.reset();
|
||||
m_last_result.push_back(n);
|
||||
m().dec_ref(n);
|
||||
}
|
||||
else {
|
||||
m_ast_trail.push_back(n);
|
||||
}
|
||||
}
|
||||
|
||||
void context::save_multiple_ast_trail(ast * n) {
|
||||
if (m_user_ref_count)
|
||||
m_last_result.push_back(n);
|
||||
else
|
||||
m_ast_trail.push_back(n);
|
||||
}
|
||||
|
||||
void context::reset_last_result() {
|
||||
if (m_user_ref_count)
|
||||
m_last_result.reset();
|
||||
m_last_obj = 0;
|
||||
}
|
||||
|
||||
void context::save_object(object * r) {
|
||||
m_last_obj = r;
|
||||
}
|
||||
|
||||
void context::handle_exception(z3_exception & ex) {
|
||||
if (ex.has_error_code()) {
|
||||
switch(ex.error_code()) {
|
||||
case ERR_MEMOUT:
|
||||
set_error_code(Z3_MEMOUT_FAIL);
|
||||
break;
|
||||
case ERR_PARSER:
|
||||
set_error_code(Z3_PARSER_ERROR);
|
||||
break;
|
||||
case ERR_INI_FILE:
|
||||
set_error_code(Z3_INVALID_ARG);
|
||||
break;
|
||||
case ERR_OPEN_FILE:
|
||||
set_error_code(Z3_FILE_ACCESS_ERROR);
|
||||
break;
|
||||
default:
|
||||
set_error_code(Z3_INTERNAL_FATAL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
m_exception_msg = ex.msg();
|
||||
set_error_code(Z3_EXCEPTION);
|
||||
}
|
||||
}
|
||||
|
||||
void context::invoke_error_handler(Z3_error_code c) {
|
||||
if (m_error_handler) {
|
||||
if (g_z3_log) {
|
||||
// error handler can do crazy stuff such as longjmp
|
||||
g_z3_log_enabled = true;
|
||||
}
|
||||
m_error_handler(reinterpret_cast<Z3_context>(this), c);
|
||||
}
|
||||
}
|
||||
|
||||
void context::check_sorts(ast * n) {
|
||||
if (!m().check_sorts(n)) {
|
||||
switch(n->get_kind()) {
|
||||
case AST_APP: {
|
||||
std::ostringstream buffer;
|
||||
app * a = to_app(n);
|
||||
buffer << mk_pp(a->get_decl(), m()) << " applied to: ";
|
||||
if (a->get_num_args() > 1) buffer << "\n";
|
||||
for (unsigned i = 0; i < a->get_num_args(); ++i) {
|
||||
buffer << mk_bounded_pp(a->get_arg(i), m(), 3) << " of sort ";
|
||||
buffer << mk_pp(m().get_sort(a->get_arg(i)), m()) << "\n";
|
||||
}
|
||||
warning_msg("%s",buffer.str().c_str());
|
||||
break;
|
||||
}
|
||||
case AST_VAR:
|
||||
case AST_QUANTIFIER:
|
||||
case AST_SORT:
|
||||
case AST_FUNC_DECL:
|
||||
break;
|
||||
}
|
||||
set_error_code(Z3_SORT_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------
|
||||
//
|
||||
// Solver interface for backward compatibility
|
||||
//
|
||||
// ------------------------
|
||||
|
||||
smt::solver & context::get_solver() {
|
||||
if (!m_solver) {
|
||||
m_solver = alloc(smt::solver, m_manager, m_params);
|
||||
}
|
||||
return *m_solver;
|
||||
}
|
||||
|
||||
void context::assert_cnstr(expr * a) {
|
||||
get_solver().assert_expr(a);
|
||||
}
|
||||
|
||||
lbool context::check(model_ref & m) {
|
||||
flet<bool> searching(m_searching, true);
|
||||
lbool r;
|
||||
r = get_solver().check();
|
||||
if (r != l_false)
|
||||
get_solver().get_model(m);
|
||||
return r;
|
||||
}
|
||||
|
||||
void context::push() {
|
||||
get_solver().push();
|
||||
if (!m_user_ref_count) {
|
||||
m_ast_lim.push_back(m_ast_trail.size());
|
||||
m_replay_stack.push_back(0);
|
||||
}
|
||||
}
|
||||
|
||||
void context::pop(unsigned num_scopes) {
|
||||
for (unsigned i = 0; i < num_scopes; ++i) {
|
||||
if (!m_user_ref_count) {
|
||||
unsigned sz = m_ast_lim.back();
|
||||
m_ast_lim.pop_back();
|
||||
dealloc(m_replay_stack.back());
|
||||
m_replay_stack.pop_back();
|
||||
while (m_ast_trail.size() > sz) {
|
||||
m_ast_trail.pop_back();
|
||||
}
|
||||
}
|
||||
}
|
||||
get_solver().pop(num_scopes);
|
||||
}
|
||||
|
||||
// ------------------------
|
||||
//
|
||||
// Parser interface for backward compatibility
|
||||
//
|
||||
// ------------------------
|
||||
|
||||
void context::reset_parser() {
|
||||
if (m_smtlib_parser) {
|
||||
dealloc(m_smtlib_parser);
|
||||
m_smtlib_parser = 0;
|
||||
m_smtlib_parser_has_decls = false;
|
||||
m_smtlib_parser_decls.reset();
|
||||
m_smtlib_parser_sorts.reset();
|
||||
}
|
||||
SASSERT(!m_smtlib_parser_has_decls);
|
||||
}
|
||||
|
||||
void context::extract_smtlib_parser_decls() {
|
||||
if (m_smtlib_parser) {
|
||||
if (!m_smtlib_parser_has_decls) {
|
||||
smtlib::symtable * table = m_smtlib_parser->get_benchmark()->get_symtable();
|
||||
table->get_func_decls(m_smtlib_parser_decls);
|
||||
table->get_sorts(m_smtlib_parser_sorts);
|
||||
m_smtlib_parser_has_decls = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
m_smtlib_parser_decls.reset();
|
||||
m_smtlib_parser_sorts.reset();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// ------------------------
|
||||
//
|
||||
// Context creation API
|
||||
//
|
||||
// ------------------------
|
||||
|
||||
extern "C" {
|
||||
|
||||
Z3_context Z3_API Z3_mk_context(Z3_config c) {
|
||||
LOG_Z3_mk_context(c);
|
||||
memory::initialize(0);
|
||||
Z3_context r = reinterpret_cast<Z3_context>(alloc(api::context, reinterpret_cast<api::config_params*>(c), false));
|
||||
RETURN_Z3(r);
|
||||
}
|
||||
|
||||
Z3_context Z3_API Z3_mk_context_rc(Z3_config c) {
|
||||
LOG_Z3_mk_context_rc(c);
|
||||
memory::initialize(0);
|
||||
Z3_context r = reinterpret_cast<Z3_context>(alloc(api::context, reinterpret_cast<api::config_params*>(c), true));
|
||||
RETURN_Z3(r);
|
||||
}
|
||||
|
||||
void Z3_API Z3_del_context(Z3_context c) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_del_context(c);
|
||||
RESET_ERROR_CODE();
|
||||
dealloc(mk_c(c));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_interrupt(Z3_context c) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_interrupt(c);
|
||||
mk_c(c)->interrupt();
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_toggle_warning_messages(Z3_bool enabled) {
|
||||
LOG_Z3_toggle_warning_messages(enabled);
|
||||
enable_warning_messages(enabled != 0);
|
||||
}
|
||||
|
||||
void Z3_API Z3_inc_ref(Z3_context c, Z3_ast a) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_inc_ref(c, a);
|
||||
RESET_ERROR_CODE();
|
||||
mk_c(c)->m().inc_ref(to_ast(a));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_dec_ref(Z3_context c, Z3_ast a) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_dec_ref(c, a);
|
||||
RESET_ERROR_CODE();
|
||||
if (to_ast(a)->get_ref_count() == 0) {
|
||||
SET_ERROR_CODE(Z3_DEC_REF_ERROR);
|
||||
return;
|
||||
}
|
||||
mk_c(c)->m().dec_ref(to_ast(a));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
Z3_bool Z3_API Z3_set_logic(Z3_context c, Z3_string logic) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_set_logic(c, logic);
|
||||
RESET_ERROR_CODE();
|
||||
return mk_c(c)->get_solver().set_logic(symbol(logic));
|
||||
Z3_CATCH_RETURN(Z3_FALSE);
|
||||
}
|
||||
|
||||
void Z3_API Z3_get_version(unsigned * major,
|
||||
unsigned * minor,
|
||||
unsigned * build_number,
|
||||
unsigned * revision_number) {
|
||||
LOG_Z3_get_version(major, minor, build_number, revision_number);
|
||||
*major = Z3_MAJOR_VERSION;
|
||||
*minor = Z3_MINOR_VERSION;
|
||||
*build_number = Z3_BUILD_NUMBER;
|
||||
*revision_number = Z3_REVISION_NUMBER;
|
||||
}
|
||||
|
||||
void Z3_API Z3_reset_memory(void) {
|
||||
LOG_Z3_reset_memory();
|
||||
memory::finalize();
|
||||
memory::initialize(0);
|
||||
}
|
||||
|
||||
Z3_error_code Z3_API Z3_get_error_code(Z3_context c) {
|
||||
LOG_Z3_get_error_code(c);
|
||||
return mk_c(c)->get_error_code();
|
||||
}
|
||||
|
||||
void Z3_API Z3_set_error_handler(Z3_context c, Z3_error_handler h) {
|
||||
RESET_ERROR_CODE();
|
||||
mk_c(c)->set_error_handler(h);
|
||||
// [Leo]: using exception handling, we don't need global error handlers anymore
|
||||
}
|
||||
|
||||
void Z3_API Z3_set_error(__in Z3_context c, __in Z3_error_code e) {
|
||||
SET_ERROR_CODE(e);
|
||||
}
|
||||
|
||||
static char const * _get_error_msg_ex(Z3_context c, Z3_error_code err) {
|
||||
switch(err) {
|
||||
case Z3_OK: return "ok";
|
||||
case Z3_SORT_ERROR: return "type error";
|
||||
case Z3_IOB: return "index out of bounds";
|
||||
case Z3_INVALID_ARG: return "invalid argument";
|
||||
case Z3_PARSER_ERROR: return "parser error";
|
||||
case Z3_NO_PARSER: return "parser (data) is not available";
|
||||
case Z3_INVALID_PATTERN: return "invalid pattern";
|
||||
case Z3_MEMOUT_FAIL: return "out of memory";
|
||||
case Z3_FILE_ACCESS_ERROR: return "file access error";
|
||||
case Z3_INTERNAL_FATAL: return "internal error";
|
||||
case Z3_INVALID_USAGE: return "invalid usage";
|
||||
case Z3_DEC_REF_ERROR: return "invalid dec_ref command";
|
||||
case Z3_EXCEPTION: return c == 0 ? "Z3 exception" : mk_c(c)->get_exception_msg();
|
||||
default: return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
char const * Z3_API Z3_get_error_msg(Z3_error_code err) {
|
||||
LOG_Z3_get_error_msg(err);
|
||||
return _get_error_msg_ex(0, err);
|
||||
}
|
||||
|
||||
char const * Z3_API Z3_get_error_msg_ex(Z3_context c, Z3_error_code err) {
|
||||
LOG_Z3_get_error_msg_ex(c, err);
|
||||
return _get_error_msg_ex(c, err);
|
||||
}
|
||||
|
||||
void Z3_API Z3_persist_ast(Z3_context c, Z3_ast n, unsigned num_scopes) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_persist_ast(c, n, num_scopes);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_VALID_AST(to_ast(n), );
|
||||
mk_c(c)->persist_ast(to_ast(n), num_scopes);
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_set_ast_print_mode(Z3_context c, Z3_ast_print_mode mode) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_set_ast_print_mode(c, mode);
|
||||
RESET_ERROR_CODE();
|
||||
mk_c(c)->set_print_mode(mode);
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
ast_manager & Z3_API Z3_get_manager(__in Z3_context c) {
|
||||
return mk_c(c)->m();
|
||||
}
|
||||
|
||||
front_end_params& Z3_API Z3_get_parameters(__in Z3_context c) {
|
||||
return mk_c(c)->fparams();
|
||||
}
|
||||
|
||||
Z3_context Z3_mk_context_from_params(front_end_params const& p) {
|
||||
api::config_params cp(p);
|
||||
return reinterpret_cast<Z3_context>(alloc(api::context, &cp));
|
||||
}
|
216
lib/api_context.h
Normal file
216
lib/api_context.h
Normal file
|
@ -0,0 +1,216 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
api_context.h
|
||||
|
||||
Abstract:
|
||||
Interface of Z3 with "external world".
|
||||
|
||||
It was called _Z3_context
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2012-02-29.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _API_CONTEXT_H_
|
||||
#define _API_CONTEXT_H_
|
||||
|
||||
#include"z3.h"
|
||||
#include"ast.h"
|
||||
#include"api_util.h"
|
||||
#include"arith_decl_plugin.h"
|
||||
#include"bv_decl_plugin.h"
|
||||
#include"datatype_decl_plugin.h"
|
||||
#include"dl_decl_plugin.h"
|
||||
#include"smt_solver.h"
|
||||
#include"front_end_params.h"
|
||||
#include"event_handler.h"
|
||||
#include"tactic_manager.h"
|
||||
|
||||
namespace smtlib {
|
||||
class parser;
|
||||
};
|
||||
|
||||
namespace api {
|
||||
class config_params;
|
||||
|
||||
Z3_search_failure mk_Z3_search_failure(smt::failure f);
|
||||
|
||||
|
||||
class context : public tactic_manager {
|
||||
class param_ini {
|
||||
front_end_params & m_params;
|
||||
public:
|
||||
param_ini(front_end_params & p);
|
||||
~param_ini();
|
||||
};
|
||||
|
||||
struct add_plugins { add_plugins(ast_manager & m); };
|
||||
|
||||
front_end_params m_params;
|
||||
param_ini m_param_ini;
|
||||
bool m_user_ref_count; //!< if true, the user is responsible for managing referenc counters.
|
||||
ast_manager m_manager;
|
||||
add_plugins m_plugins;
|
||||
|
||||
arith_util m_arith_util;
|
||||
bv_util m_bv_util;
|
||||
datalog::dl_decl_util m_datalog_util;
|
||||
|
||||
smt::solver * m_solver; // General purpose solver for backward compatibility
|
||||
|
||||
ast_ref_vector m_last_result; //!< used when m_user_ref_count == true
|
||||
ast_ref_vector m_ast_trail; //!< used when m_user_ref_count == false
|
||||
unsigned_vector m_ast_lim;
|
||||
ptr_vector<ast_ref_vector> m_replay_stack;
|
||||
|
||||
ref<api::object> m_last_obj; //!< reference to the last API object returned by the APIs
|
||||
|
||||
family_id m_basic_fid;
|
||||
family_id m_array_fid;
|
||||
family_id m_arith_fid;
|
||||
family_id m_bv_fid;
|
||||
family_id m_dt_fid;
|
||||
family_id m_datalog_fid;
|
||||
datatype_decl_plugin * m_dt_plugin;
|
||||
|
||||
std::string m_string_buffer; // temporary buffer used to cache strings sent to the "external" world.
|
||||
|
||||
Z3_error_code m_error_code;
|
||||
Z3_error_handler * m_error_handler;
|
||||
std::string m_exception_msg; // catch the message associated with a Z3 exception
|
||||
bool m_searching;
|
||||
Z3_ast_print_mode m_print_mode;
|
||||
|
||||
event_handler * m_interruptable; // Reference to an object that can be interrupted by Z3_interrupt
|
||||
public:
|
||||
// Scoped obj for setting m_interruptable
|
||||
class set_interruptable {
|
||||
context & m_ctx;
|
||||
public:
|
||||
set_interruptable(context & ctx, event_handler & i);
|
||||
~set_interruptable();
|
||||
};
|
||||
|
||||
// ------------------------
|
||||
//
|
||||
// Core
|
||||
//
|
||||
// ------------------------
|
||||
|
||||
context(config_params * p, bool user_ref_count = false);
|
||||
~context();
|
||||
|
||||
front_end_params & fparams() { return m_params; }
|
||||
ast_manager & m() { return m_manager; }
|
||||
arith_util & autil() { return m_arith_util; }
|
||||
bv_util & bvutil() { return m_bv_util; }
|
||||
datalog::dl_decl_util & datalog_util() { return m_datalog_util; }
|
||||
family_id get_basic_fid() const { return m_basic_fid; }
|
||||
family_id get_array_fid() const { return m_array_fid; }
|
||||
family_id get_arith_fid() const { return m_arith_fid; }
|
||||
family_id get_bv_fid() const { return m_bv_fid; }
|
||||
family_id get_dt_fid() const { return m_dt_fid; }
|
||||
family_id get_datalog_fid() const { return m_datalog_fid; }
|
||||
datatype_decl_plugin * get_dt_plugin() const { return m_dt_plugin; }
|
||||
|
||||
Z3_error_code get_error_code() const { return m_error_code; }
|
||||
void reset_error_code() { m_error_code = Z3_OK; }
|
||||
void set_error_code(Z3_error_code err);
|
||||
void set_error_handler(Z3_error_handler h) { m_error_handler = h; }
|
||||
// Sign an error if solver is searching
|
||||
void check_searching();
|
||||
|
||||
Z3_ast_print_mode get_print_mode() const { return m_print_mode; }
|
||||
void set_print_mode(Z3_ast_print_mode m) { m_print_mode = m; }
|
||||
|
||||
// Store a copy of str in m_string_buffer, and return a reference to it.
|
||||
// This method is used to communicate local/internal strings with the "external world"
|
||||
char * mk_external_string(char const * str);
|
||||
char * mk_external_string(std::string const & str);
|
||||
|
||||
// Create a numeral of the given sort
|
||||
expr * mk_numeral_core(rational const & n, sort * s);
|
||||
|
||||
// Return a conjuction that will be exposed to the "external" world.
|
||||
expr * mk_and(unsigned num_exprs, expr * const * exprs);
|
||||
|
||||
// Hack for preventing an AST for being GC when ref-count is not used
|
||||
void persist_ast(ast * n, unsigned num_scopes);
|
||||
|
||||
// "Save" an AST that will exposed to the "external" world.
|
||||
void save_ast_trail(ast * n);
|
||||
|
||||
// Similar to previous method, but it "adds" n to the result.
|
||||
void save_multiple_ast_trail(ast * n);
|
||||
|
||||
// Reset the cache that stores the ASTs exposed in the previous call.
|
||||
// This is a NOOP if ref-count is disabled.
|
||||
void reset_last_result();
|
||||
|
||||
// "Save" a reference to an object that is exposed by the API
|
||||
void save_object(object * r);
|
||||
|
||||
// Process exception: save message and set error code.
|
||||
void handle_exception(z3_exception & ex);
|
||||
char const * get_exception_msg() const { return m_exception_msg.c_str(); }
|
||||
|
||||
// Interrupt the current interruptable object
|
||||
void interrupt();
|
||||
|
||||
void invoke_error_handler(Z3_error_code c);
|
||||
|
||||
static void out_of_memory_handler(void * _ctx);
|
||||
|
||||
void check_sorts(ast * n);
|
||||
// ------------------------
|
||||
//
|
||||
// Solver interface for backward compatibility
|
||||
//
|
||||
// ------------------------
|
||||
|
||||
bool has_solver() const { return m_solver != 0; }
|
||||
smt::solver & get_solver();
|
||||
void assert_cnstr(expr * a);
|
||||
lbool check(model_ref & m);
|
||||
void push();
|
||||
void pop(unsigned num_scopes);
|
||||
unsigned get_num_scopes() const { return m_ast_lim.size(); }
|
||||
|
||||
// ------------------------
|
||||
//
|
||||
// Parser interface for backward compatibility
|
||||
//
|
||||
// ------------------------
|
||||
|
||||
// TODO: move to a "parser" object visible to the external world.
|
||||
std::string m_smtlib_error_buffer;
|
||||
smtlib::parser * m_smtlib_parser;
|
||||
bool m_smtlib_parser_has_decls;
|
||||
ptr_vector<func_decl> m_smtlib_parser_decls;
|
||||
ptr_vector<sort> m_smtlib_parser_sorts;
|
||||
|
||||
void reset_parser();
|
||||
void extract_smtlib_parser_decls();
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
inline api::context * mk_c(Z3_context c) { return reinterpret_cast<api::context*>(c); }
|
||||
#define RESET_ERROR_CODE() { mk_c(c)->reset_error_code(); }
|
||||
#define SET_ERROR_CODE(ERR) { mk_c(c)->set_error_code(ERR); }
|
||||
#define CHECK_NON_NULL(_p_,_ret_) { if (_p_ == 0) { SET_ERROR_CODE(Z3_INVALID_ARG); return _ret_; } }
|
||||
#define CHECK_VALID_AST(_a_, _ret_) { if (_a_ == 0 || !CHECK_REF_COUNT(_a_)) { SET_ERROR_CODE(Z3_INVALID_ARG); return _ret_; } }
|
||||
#define CHECK_SEARCHING(c) mk_c(c)->check_searching();
|
||||
inline bool is_expr(Z3_ast a) { return is_expr(to_ast(a)); }
|
||||
inline bool is_bool_expr(Z3_context c, Z3_ast a) { return is_expr(a) && mk_c(c)->m().is_bool(to_expr(a)); }
|
||||
#define CHECK_FORMULA(_a_, _ret_) { if (_a_ == 0 || !CHECK_REF_COUNT(_a_) || !is_bool_expr(c, _a_)) { SET_ERROR_CODE(Z3_INVALID_ARG); return _ret_; } }
|
||||
inline void check_sorts(Z3_context c, ast * n) { mk_c(c)->check_sorts(n); }
|
||||
|
||||
#endif
|
561
lib/api_datalog.cpp
Normal file
561
lib/api_datalog.cpp
Normal file
|
@ -0,0 +1,561 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
api_datalog.cpp
|
||||
|
||||
Abstract:
|
||||
Datalog API
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2012-02-29.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include"api_datalog.h"
|
||||
#include"api_context.h"
|
||||
#include"api_util.h"
|
||||
#include"dl_context.h"
|
||||
#include"ast_pp.h"
|
||||
#include"api_ast_vector.h"
|
||||
#include"api_log_macros.h"
|
||||
#include"api_stats.h"
|
||||
#include"datalog_parser.h"
|
||||
#include"cancel_eh.h"
|
||||
#include"scoped_timer.h"
|
||||
|
||||
namespace api {
|
||||
|
||||
fixedpoint_context::fixedpoint_context(ast_manager& m, front_end_params& p) :
|
||||
m_state(0),
|
||||
m_reduce_app(0),
|
||||
m_reduce_assign(0),
|
||||
m_context(m, p),
|
||||
m_trail(m) {}
|
||||
|
||||
|
||||
void fixedpoint_context::set_state(void* state) {
|
||||
SASSERT(!m_state);
|
||||
m_state = state;
|
||||
symbol name("datalog_relation");
|
||||
ast_manager& m = m_context.get_manager();
|
||||
if (!m.has_plugin(name)) {
|
||||
m.register_plugin(name, alloc(datalog::dl_decl_plugin));
|
||||
}
|
||||
datalog::relation_manager& r = m_context.get_rmanager();
|
||||
r.register_plugin(alloc(datalog::external_relation_plugin, *this, r));
|
||||
}
|
||||
|
||||
void fixedpoint_context::reduce(func_decl* f, unsigned num_args, expr * const* args, expr_ref& result) {
|
||||
expr* r = 0;
|
||||
if (m_reduce_app) {
|
||||
m_reduce_app(m_state, f, num_args, args, &r);
|
||||
result = r;
|
||||
m_trail.push_back(f);
|
||||
for (unsigned i = 0; i < num_args; ++i) {
|
||||
m_trail.push_back(args[i]);
|
||||
}
|
||||
m_trail.push_back(r);
|
||||
}
|
||||
// allow fallthrough.
|
||||
if (r == 0) {
|
||||
ast_manager& m = m_context.get_manager();
|
||||
result = m.mk_app(f, num_args, args);
|
||||
}
|
||||
}
|
||||
|
||||
// overwrite terms passed in outs vector with values computed by function.
|
||||
void fixedpoint_context::reduce_assign(func_decl* f, unsigned num_args, expr * const* args, unsigned num_out, expr* const* outs) {
|
||||
if (m_reduce_assign) {
|
||||
m_trail.push_back(f);
|
||||
for (unsigned i = 0; i < num_args; ++i) {
|
||||
m_trail.push_back(args[i]);
|
||||
}
|
||||
m_reduce_assign(m_state, f, num_args, args, num_out, outs);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void fixedpoint_context::add_rule(expr* rule, symbol const& name) {
|
||||
m_context.add_rule(rule, name);
|
||||
}
|
||||
|
||||
void fixedpoint_context::update_rule(expr* rule, symbol const& name) {
|
||||
m_context.update_rule(rule, name);
|
||||
}
|
||||
|
||||
void fixedpoint_context::add_table_fact(func_decl* r, unsigned num_args, unsigned args[]) {
|
||||
m_context.add_table_fact(r, num_args, args);
|
||||
}
|
||||
|
||||
unsigned fixedpoint_context::get_num_levels(func_decl* pred) {
|
||||
return m_context.get_num_levels(pred);
|
||||
}
|
||||
|
||||
expr_ref fixedpoint_context::get_cover_delta(int level, func_decl* pred) {
|
||||
return m_context.get_cover_delta(level, pred);
|
||||
}
|
||||
|
||||
void fixedpoint_context::add_cover(int level, func_decl* pred, expr* predicate) {
|
||||
m_context.add_cover(level, pred, predicate);
|
||||
}
|
||||
|
||||
std::string fixedpoint_context::get_last_status() {
|
||||
datalog::execution_result status = m_context.get_status();
|
||||
switch(status) {
|
||||
case datalog::INPUT_ERROR:
|
||||
return "input error";
|
||||
case datalog::OK:
|
||||
return "ok";
|
||||
case datalog::TIMEOUT:
|
||||
return "timeout";
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
std::string fixedpoint_context::to_string(unsigned num_queries, expr*const* queries) {
|
||||
std::stringstream str;
|
||||
m_context.display_smt2(num_queries, queries, str);
|
||||
return str.str();
|
||||
}
|
||||
|
||||
void fixedpoint_context::simplify_rules(
|
||||
unsigned num_rules, expr* const* rules,
|
||||
unsigned num_outputs, func_decl* const* outputs, expr_ref_vector& result) {
|
||||
ast_manager& m = m_context.get_manager();
|
||||
|
||||
datalog::context ctx(m, m_context.get_fparams());
|
||||
datalog::rule_manager& rm = ctx.get_rule_manager();
|
||||
for (unsigned i = 0; i < num_rules; ++i) {
|
||||
expr* rule = rules[i], *body, *head;
|
||||
while (true) {
|
||||
if (is_quantifier(rule)) {
|
||||
rule = to_quantifier(rule)->get_expr();
|
||||
}
|
||||
else if (m.is_implies(rule, body, head)) {
|
||||
rule = head;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (is_app(rule)) {
|
||||
func_decl* r = to_app(rule)->get_decl();
|
||||
if (!ctx.is_predicate(r)) {
|
||||
ctx.register_predicate(r);
|
||||
if (num_outputs == 0) {
|
||||
ctx.set_output_predicate(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (unsigned i = 0; i < num_outputs; ++i) {
|
||||
ctx.set_output_predicate(outputs[i]);
|
||||
}
|
||||
for (unsigned i = 0; i < num_rules; ++i) {
|
||||
expr* rule = rules[i];
|
||||
ctx.add_rule(rule, symbol::null);
|
||||
}
|
||||
model_converter_ref mc; // not exposed.
|
||||
proof_converter_ref pc; // not exposed.
|
||||
ctx.apply_default_transformation(mc, pc);
|
||||
datalog::rule_set const& new_rules = ctx.get_rules();
|
||||
datalog::rule_set::iterator it = new_rules.begin(), end = new_rules.end();
|
||||
for (; it != end; ++it) {
|
||||
datalog::rule* r = *it;
|
||||
expr_ref fml(m);
|
||||
r->to_formula(fml);
|
||||
result.push_back(fml);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
extern "C" {
|
||||
|
||||
////////////////////////////////////
|
||||
// Datalog utilities
|
||||
//
|
||||
|
||||
|
||||
unsigned Z3_API Z3_get_relation_arity(Z3_context c, Z3_sort s) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_relation_arity(c, s);
|
||||
RESET_ERROR_CODE();
|
||||
sort * r = to_sort(s);
|
||||
if (Z3_get_sort_kind(c, s) != Z3_RELATION_SORT) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
return 0;
|
||||
}
|
||||
return r->get_num_parameters();
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_sort Z3_API Z3_get_relation_column(Z3_context c, Z3_sort s, unsigned col) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_relation_column(c, s, col);
|
||||
RESET_ERROR_CODE();
|
||||
sort * r = to_sort(s);
|
||||
if (Z3_get_sort_kind(c, s) != Z3_RELATION_SORT) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
if (col >= r->get_num_parameters()) {
|
||||
SET_ERROR_CODE(Z3_IOB);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
parameter const& p = r->get_parameter(col);
|
||||
if (!p.is_ast() || !is_sort(p.get_ast())) {
|
||||
UNREACHABLE();
|
||||
warning_msg("Sort parameter expected at %d", col);
|
||||
SET_ERROR_CODE(Z3_INTERNAL_FATAL);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
Z3_sort res = of_sort(to_sort(p.get_ast()));
|
||||
RETURN_Z3(res);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_sort Z3_API Z3_mk_finite_domain_sort(Z3_context c, Z3_symbol name, unsigned __int64 size) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_finite_domain_sort(c, name, size);
|
||||
RESET_ERROR_CODE();
|
||||
sort* s = mk_c(c)->datalog_util().mk_sort(to_symbol(name), size);
|
||||
mk_c(c)->save_ast_trail(s);
|
||||
RETURN_Z3(of_sort(s));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_bool Z3_API Z3_get_finite_domain_sort_size(Z3_context c, Z3_sort s, unsigned __int64 * out) {
|
||||
Z3_TRY;
|
||||
if (out) {
|
||||
*out = 0;
|
||||
}
|
||||
if (Z3_get_sort_kind(c, s) != Z3_FINITE_DOMAIN_SORT) {
|
||||
return Z3_FALSE;
|
||||
}
|
||||
if (!out) {
|
||||
return Z3_FALSE;
|
||||
}
|
||||
// must start loggging here, since function uses Z3_get_sort_kind above
|
||||
LOG_Z3_get_finite_domain_sort_size(c, s, out);
|
||||
RESET_ERROR_CODE();
|
||||
VERIFY(mk_c(c)->datalog_util().try_get_size(to_sort(s), *out));
|
||||
return Z3_TRUE;
|
||||
|
||||
Z3_CATCH_RETURN(Z3_FALSE);
|
||||
}
|
||||
|
||||
Z3_fixedpoint Z3_API Z3_mk_fixedpoint(Z3_context c) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_fixedpoint(c);
|
||||
RESET_ERROR_CODE();
|
||||
Z3_fixedpoint_ref * d = alloc(Z3_fixedpoint_ref);
|
||||
d->m_datalog = alloc(api::fixedpoint_context, mk_c(c)->m(), mk_c(c)->fparams());
|
||||
mk_c(c)->save_object(d);
|
||||
Z3_fixedpoint r = of_datalog(d);
|
||||
RETURN_Z3(r);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
void Z3_API Z3_fixedpoint_inc_ref(Z3_context c, Z3_fixedpoint s) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_fixedpoint_inc_ref(c, s);
|
||||
RESET_ERROR_CODE();
|
||||
to_fixedpoint(s)->inc_ref();
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_fixedpoint_dec_ref(Z3_context c, Z3_fixedpoint s) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_fixedpoint_dec_ref(c, s);
|
||||
RESET_ERROR_CODE();
|
||||
to_fixedpoint(s)->dec_ref();
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_fixedpoint_assert(Z3_context c, Z3_fixedpoint d, Z3_ast a) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_fixedpoint_assert(c, d, a);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_FORMULA(a,);
|
||||
to_fixedpoint_ref(d)->ctx().assert_expr(to_expr(a));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_fixedpoint_add_rule(Z3_context c, Z3_fixedpoint d, Z3_ast a, Z3_symbol name) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_fixedpoint_add_rule(c, d, a, name);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_FORMULA(a,);
|
||||
to_fixedpoint_ref(d)->add_rule(to_expr(a), to_symbol(name));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_fixedpoint_add_fact(Z3_context c, Z3_fixedpoint d,
|
||||
Z3_func_decl r, unsigned num_args, unsigned args[]) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_fixedpoint_add_fact(c, d, r, num_args, args);
|
||||
RESET_ERROR_CODE();
|
||||
to_fixedpoint_ref(d)->add_table_fact(to_func_decl(r), num_args, args);
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
Z3_lbool Z3_API Z3_fixedpoint_query(Z3_context c,Z3_fixedpoint d, Z3_ast q) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_fixedpoint_query(c, d, q);
|
||||
RESET_ERROR_CODE();
|
||||
lbool r = l_undef;
|
||||
cancel_eh<api::fixedpoint_context> eh(*to_fixedpoint_ref(d));
|
||||
unsigned timeout = to_fixedpoint(d)->m_params.get_uint(":timeout", UINT_MAX);
|
||||
api::context::set_interruptable(*(mk_c(c)), eh);
|
||||
{
|
||||
scoped_timer timer(timeout, &eh);
|
||||
try {
|
||||
r = to_fixedpoint_ref(d)->ctx().query(to_expr(q));
|
||||
}
|
||||
catch (z3_exception& ex) {
|
||||
mk_c(c)->handle_exception(ex);
|
||||
r = l_undef;
|
||||
}
|
||||
to_fixedpoint_ref(d)->ctx().cleanup();
|
||||
}
|
||||
return of_lbool(r);
|
||||
Z3_CATCH_RETURN(Z3_L_UNDEF);
|
||||
}
|
||||
|
||||
Z3_lbool Z3_API Z3_fixedpoint_query_relations(
|
||||
__in Z3_context c,__in Z3_fixedpoint d,
|
||||
__in unsigned num_relations, Z3_func_decl const relations[]) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_fixedpoint_query_relations(c, d, num_relations, relations);
|
||||
RESET_ERROR_CODE();
|
||||
lbool r = l_undef;
|
||||
unsigned timeout = to_fixedpoint(d)->m_params.get_uint(":timeout", UINT_MAX);
|
||||
cancel_eh<api::fixedpoint_context> eh(*to_fixedpoint_ref(d));
|
||||
api::context::set_interruptable(*(mk_c(c)), eh);
|
||||
{
|
||||
scoped_timer timer(timeout, &eh);
|
||||
try {
|
||||
r = to_fixedpoint_ref(d)->ctx().dl_query(num_relations, to_func_decls(relations));
|
||||
}
|
||||
catch (z3_exception& ex) {
|
||||
mk_c(c)->handle_exception(ex);
|
||||
r = l_undef;
|
||||
}
|
||||
to_fixedpoint_ref(d)->ctx().cleanup();
|
||||
}
|
||||
return of_lbool(r);
|
||||
Z3_CATCH_RETURN(Z3_L_UNDEF);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_fixedpoint_get_answer(Z3_context c, Z3_fixedpoint d) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_fixedpoint_get_answer(c, d);
|
||||
RESET_ERROR_CODE();
|
||||
expr* e = to_fixedpoint_ref(d)->ctx().get_answer_as_formula();
|
||||
mk_c(c)->save_ast_trail(e);
|
||||
RETURN_Z3(of_expr(e));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_string Z3_API Z3_fixedpoint_get_reason_unknown(Z3_context c,Z3_fixedpoint d) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_fixedpoint_get_reason_unknown(c, d);
|
||||
RESET_ERROR_CODE();
|
||||
return mk_c(c)->mk_external_string(to_fixedpoint_ref(d)->get_last_status());
|
||||
Z3_CATCH_RETURN("");
|
||||
}
|
||||
|
||||
Z3_string Z3_API Z3_fixedpoint_to_string(
|
||||
Z3_context c,
|
||||
Z3_fixedpoint d,
|
||||
unsigned num_queries,
|
||||
Z3_ast _queries[]) {
|
||||
Z3_TRY;
|
||||
expr*const* queries = to_exprs(_queries);
|
||||
LOG_Z3_fixedpoint_to_string(c, d, num_queries, _queries);
|
||||
RESET_ERROR_CODE();
|
||||
return mk_c(c)->mk_external_string(to_fixedpoint_ref(d)->to_string(num_queries, queries));
|
||||
Z3_CATCH_RETURN("");
|
||||
}
|
||||
|
||||
Z3_stats Z3_API Z3_fixedpoint_get_statistics(Z3_context c,Z3_fixedpoint d) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_fixedpoint_get_statistics(c, d);
|
||||
RESET_ERROR_CODE();
|
||||
Z3_stats_ref * st = alloc(Z3_stats_ref);
|
||||
to_fixedpoint_ref(d)->ctx().collect_statistics(st->m_stats);
|
||||
mk_c(c)->save_object(st);
|
||||
Z3_stats r = of_stats(st);
|
||||
RETURN_Z3(r);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
void Z3_API Z3_fixedpoint_register_relation(Z3_context c,Z3_fixedpoint d, Z3_func_decl f) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_fixedpoint_register_relation(c, d, f);
|
||||
to_fixedpoint_ref(d)->ctx().register_predicate(to_func_decl(f));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_fixedpoint_set_predicate_representation(
|
||||
Z3_context c,
|
||||
Z3_fixedpoint d,
|
||||
Z3_func_decl f,
|
||||
unsigned num_relations,
|
||||
Z3_symbol const relation_kinds[]) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_fixedpoint_set_predicate_representation(c, d, f, num_relations, relation_kinds);
|
||||
svector<symbol> kinds;
|
||||
for (unsigned i = 0; i < num_relations; ++i) {
|
||||
kinds.push_back(to_symbol(relation_kinds[i]));
|
||||
}
|
||||
to_fixedpoint_ref(d)->ctx().set_predicate_representation(to_func_decl(f), num_relations, kinds.c_ptr());
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_fixedpoint_set_reduce_assign_callback(
|
||||
Z3_context c, Z3_fixedpoint d, Z3_fixedpoint_reduce_assign_callback_fptr f) {
|
||||
Z3_TRY;
|
||||
// no logging
|
||||
to_fixedpoint_ref(d)->set_reduce_assign((reduce_assign_callback_fptr)f);
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_fixedpoint_set_reduce_app_callback(
|
||||
Z3_context c, Z3_fixedpoint d, Z3_fixedpoint_reduce_app_callback_fptr f) {
|
||||
Z3_TRY;
|
||||
// no logging
|
||||
to_fixedpoint_ref(d)->set_reduce_app((reduce_app_callback_fptr)f);
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
Z3_ast_vector Z3_API Z3_fixedpoint_simplify_rules(
|
||||
Z3_context c,
|
||||
Z3_fixedpoint d,
|
||||
unsigned num_rules,
|
||||
Z3_ast _rules[],
|
||||
unsigned num_outputs,
|
||||
Z3_func_decl _outputs[]) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_fixedpoint_simplify_rules(c, d, num_rules, _rules, num_outputs, _outputs);
|
||||
RESET_ERROR_CODE();
|
||||
expr** rules = (expr**)_rules;
|
||||
func_decl** outputs = (func_decl**)_outputs;
|
||||
ast_manager& m = mk_c(c)->m();
|
||||
expr_ref_vector result(m);
|
||||
to_fixedpoint_ref(d)->simplify_rules(num_rules, rules, num_outputs, outputs, result);
|
||||
Z3_ast_vector_ref* v = alloc(Z3_ast_vector_ref, mk_c(c)->m());
|
||||
mk_c(c)->save_object(v);
|
||||
for (unsigned i = 0; i < result.size(); ++i) {
|
||||
v->m_ast_vector.push_back(result[i].get());
|
||||
}
|
||||
RETURN_Z3(of_ast_vector(v));
|
||||
Z3_CATCH_RETURN(0)
|
||||
}
|
||||
|
||||
|
||||
void Z3_API Z3_fixedpoint_init(Z3_context c,Z3_fixedpoint d, void* state) {
|
||||
Z3_TRY;
|
||||
// not logged
|
||||
to_fixedpoint_ref(d)->set_state(state);
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
|
||||
void Z3_API Z3_fixedpoint_update_rule(Z3_context c, Z3_fixedpoint d, Z3_ast a, Z3_symbol name) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_fixedpoint_update_rule(c, d, a, name);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_FORMULA(a,);
|
||||
to_fixedpoint_ref(d)->update_rule(to_expr(a), to_symbol(name));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
unsigned Z3_API Z3_fixedpoint_get_num_levels(Z3_context c, Z3_fixedpoint d, Z3_func_decl pred) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_fixedpoint_get_num_levels(c, d, pred);
|
||||
RESET_ERROR_CODE();
|
||||
return to_fixedpoint_ref(d)->get_num_levels(to_func_decl(pred));
|
||||
Z3_CATCH_RETURN(0)
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_fixedpoint_get_cover_delta(Z3_context c, Z3_fixedpoint d, int level, Z3_func_decl pred) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_fixedpoint_get_cover_delta(c, d, level, pred);
|
||||
RESET_ERROR_CODE();
|
||||
expr_ref r = to_fixedpoint_ref(d)->get_cover_delta(level, to_func_decl(pred));
|
||||
mk_c(c)->save_ast_trail(r);
|
||||
RETURN_Z3(of_expr(r.get()));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
void Z3_API Z3_fixedpoint_add_cover(Z3_context c, Z3_fixedpoint d, int level, Z3_func_decl pred, Z3_ast property) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_fixedpoint_add_cover(c, d, level, pred, property);
|
||||
RESET_ERROR_CODE();
|
||||
to_fixedpoint_ref(d)->add_cover(level, to_func_decl(pred), to_expr(property));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
Z3_string Z3_API Z3_fixedpoint_get_help(Z3_context c, Z3_fixedpoint d) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_fixedpoint_get_help(c, d);
|
||||
RESET_ERROR_CODE();
|
||||
std::ostringstream buffer;
|
||||
param_descrs descrs;
|
||||
to_fixedpoint_ref(d)->collect_param_descrs(descrs);
|
||||
descrs.display(buffer);
|
||||
return mk_c(c)->mk_external_string(buffer.str());
|
||||
Z3_CATCH_RETURN("");
|
||||
}
|
||||
|
||||
Z3_param_descrs Z3_API Z3_fixedpoint_get_param_descrs(Z3_context c, Z3_fixedpoint f) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_fixedpoint_get_param_descrs(c, f);
|
||||
RESET_ERROR_CODE();
|
||||
Z3_param_descrs_ref * d = alloc(Z3_param_descrs_ref);
|
||||
mk_c(c)->save_object(d);
|
||||
to_fixedpoint_ref(f)->collect_param_descrs(d->m_descrs);
|
||||
Z3_param_descrs r = of_param_descrs(d);
|
||||
RETURN_Z3(r);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
void Z3_API Z3_fixedpoint_set_params(Z3_context c, Z3_fixedpoint d, Z3_params p) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_fixedpoint_set_params(c, d, p);
|
||||
RESET_ERROR_CODE();
|
||||
param_descrs descrs;
|
||||
to_fixedpoint_ref(d)->collect_param_descrs(descrs);
|
||||
to_params(p)->m_params.validate(descrs);
|
||||
to_fixedpoint_ref(d)->updt_params(to_param_ref(p));
|
||||
to_fixedpoint(d)->m_params = to_param_ref(p);
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_fixedpoint_push(Z3_context c,Z3_fixedpoint d) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_fixedpoint_push(c, d);
|
||||
RESET_ERROR_CODE();
|
||||
to_fixedpoint_ref(d)->ctx().push();
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_fixedpoint_pop(Z3_context c,Z3_fixedpoint d) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_fixedpoint_pop(c, d);
|
||||
RESET_ERROR_CODE();
|
||||
to_fixedpoint_ref(d)->ctx().pop();
|
||||
Z3_CATCH;
|
||||
|
||||
}
|
||||
|
||||
|
||||
};
|
84
lib/api_datalog.h
Normal file
84
lib/api_datalog.h
Normal file
|
@ -0,0 +1,84 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
api_datalog.h
|
||||
|
||||
Abstract:
|
||||
Datalog API
|
||||
old external_relation_context_impl
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2012-02-29.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _API_DATALOG_H_
|
||||
#define _API_DATALOG_H_
|
||||
|
||||
#include"z3.h"
|
||||
#include"ast.h"
|
||||
#include"front_end_params.h"
|
||||
#include"dl_external_relation.h"
|
||||
#include"dl_decl_plugin.h"
|
||||
#include"smt_solver.h"
|
||||
#include"api_util.h"
|
||||
#include"dl_context.h"
|
||||
|
||||
typedef void (*reduce_app_callback_fptr)(void*, func_decl*, unsigned, expr*const*, expr**);
|
||||
typedef void (*reduce_assign_callback_fptr)(void*, func_decl*, unsigned, expr*const*, unsigned, expr*const*);
|
||||
|
||||
namespace api {
|
||||
|
||||
class fixedpoint_context : public datalog::external_relation_context {
|
||||
void * m_state;
|
||||
reduce_app_callback_fptr m_reduce_app;
|
||||
reduce_assign_callback_fptr m_reduce_assign;
|
||||
datalog::context m_context;
|
||||
ast_ref_vector m_trail;
|
||||
public:
|
||||
fixedpoint_context(ast_manager& m, front_end_params& p);
|
||||
virtual ~fixedpoint_context() {}
|
||||
family_id get_family_id() const { return const_cast<datalog::context&>(m_context).get_decl_util().get_family_id(); }
|
||||
void set_state(void* state);
|
||||
void set_reduce_app(reduce_app_callback_fptr f) { m_reduce_app = f; }
|
||||
void set_reduce_assign(reduce_assign_callback_fptr f) { m_reduce_assign = f; }
|
||||
virtual void reduce(func_decl* f, unsigned num_args, expr * const* args, expr_ref& result);
|
||||
virtual void reduce_assign(func_decl* f, unsigned num_args, expr * const* args, unsigned num_out, expr* const* outs);
|
||||
datalog::context& ctx() { return m_context; }
|
||||
void add_rule(expr* rule, symbol const& name);
|
||||
void update_rule(expr* rule, symbol const& name);
|
||||
void add_table_fact(func_decl* r, unsigned num_args, unsigned args[]);
|
||||
std::string get_last_status();
|
||||
std::string to_string(unsigned num_queries, expr*const* queries);
|
||||
void cancel() { m_context.cancel(); }
|
||||
|
||||
unsigned get_num_levels(func_decl* pred);
|
||||
expr_ref get_cover_delta(int level, func_decl* pred);
|
||||
void add_cover(int level, func_decl* pred, expr* predicate);
|
||||
void collect_param_descrs(param_descrs & p) { m_context.collect_params(p); }
|
||||
void updt_params(params_ref const& p) { m_context.updt_params(p); }
|
||||
|
||||
void simplify_rules(
|
||||
unsigned num_rules, expr* const* rules,
|
||||
unsigned num_outputs, func_decl* const* outputs, expr_ref_vector& result);
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
struct Z3_fixedpoint_ref : public api::object {
|
||||
api::fixedpoint_context * m_datalog;
|
||||
params_ref m_params;
|
||||
Z3_fixedpoint_ref():m_datalog(0) {}
|
||||
virtual ~Z3_fixedpoint_ref() { dealloc(m_datalog); }
|
||||
};
|
||||
|
||||
inline Z3_fixedpoint_ref * to_fixedpoint(Z3_fixedpoint s) { return reinterpret_cast<Z3_fixedpoint_ref *>(s); }
|
||||
inline Z3_fixedpoint of_datalog(Z3_fixedpoint_ref * s) { return reinterpret_cast<Z3_fixedpoint>(s); }
|
||||
inline api::fixedpoint_context * to_fixedpoint_ref(Z3_fixedpoint s) { return to_fixedpoint(s)->m_datalog; }
|
||||
|
||||
|
||||
#endif
|
621
lib/api_datatype.cpp
Normal file
621
lib/api_datatype.cpp
Normal file
|
@ -0,0 +1,621 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
api_datatype.cpp
|
||||
|
||||
Abstract:
|
||||
API for datatype theory
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2012-02-29.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include<iostream>
|
||||
#include"z3.h"
|
||||
#include"api_log_macros.h"
|
||||
#include"api_context.h"
|
||||
#include"api_util.h"
|
||||
#include"datatype_decl_plugin.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
Z3_sort Z3_API Z3_mk_tuple_sort(Z3_context c,
|
||||
Z3_symbol name,
|
||||
unsigned num_fields,
|
||||
Z3_symbol const field_names[],
|
||||
Z3_sort const field_sorts[],
|
||||
Z3_func_decl * mk_tuple_decl,
|
||||
Z3_func_decl proj_decls[]) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_tuple_sort(c, name, num_fields, field_names, field_sorts, mk_tuple_decl, proj_decls);
|
||||
RESET_ERROR_CODE();
|
||||
mk_c(c)->reset_last_result();
|
||||
ast_manager& m = mk_c(c)->m();
|
||||
datatype_util dt_util(m);
|
||||
|
||||
sort_ref_vector tuples(m);
|
||||
sort* tuple;
|
||||
std::string recognizer_s("is_");
|
||||
recognizer_s += to_symbol(name).str();
|
||||
symbol recognizer(recognizer_s.c_str());
|
||||
|
||||
ptr_vector<accessor_decl> acc;
|
||||
for (unsigned i = 0; i < num_fields; ++i) {
|
||||
acc.push_back(mk_accessor_decl(to_symbol(field_names[i]), type_ref(to_sort(field_sorts[i]))));
|
||||
}
|
||||
|
||||
constructor_decl* constrs[1] = { mk_constructor_decl(to_symbol(name), recognizer, acc.size(), acc.c_ptr()) };
|
||||
|
||||
{
|
||||
datatype_decl * dt = mk_datatype_decl(to_symbol(name), 1, constrs);
|
||||
bool is_ok = mk_c(c)->get_dt_plugin()->mk_datatypes(1, &dt, tuples);
|
||||
del_datatype_decl(dt);
|
||||
|
||||
if (!is_ok) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
}
|
||||
|
||||
// create tuple type
|
||||
SASSERT(tuples.size() == 1);
|
||||
tuple = tuples[0].get();
|
||||
mk_c(c)->save_multiple_ast_trail(tuple);
|
||||
|
||||
// create constructor
|
||||
SASSERT(dt_util.is_datatype(tuple));
|
||||
SASSERT(!dt_util.is_recursive(tuple));
|
||||
ptr_vector<func_decl> const * decls = dt_util.get_datatype_constructors(tuple);
|
||||
func_decl* decl = (*decls)[0];
|
||||
mk_c(c)->save_multiple_ast_trail(decl);
|
||||
*mk_tuple_decl = of_func_decl(decl);
|
||||
|
||||
// Create projections
|
||||
ptr_vector<func_decl> const * accs = dt_util.get_constructor_accessors(decl);
|
||||
if (!accs) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
ptr_vector<func_decl> const & _accs = *accs;
|
||||
SASSERT(_accs.size() == num_fields);
|
||||
for (unsigned i = 0; i < _accs.size(); i++) {
|
||||
mk_c(c)->save_multiple_ast_trail(_accs[i]);
|
||||
proj_decls[i] = of_func_decl(_accs[i]);
|
||||
}
|
||||
RETURN_Z3_mk_tuple_sort(of_sort(tuple));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_sort Z3_API Z3_mk_enumeration_sort(Z3_context c,
|
||||
Z3_symbol name,
|
||||
unsigned n,
|
||||
Z3_symbol const enum_names[],
|
||||
Z3_func_decl enum_consts[],
|
||||
Z3_func_decl enum_testers[]) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_enumeration_sort(c, name, n, enum_names, enum_consts, enum_testers);
|
||||
RESET_ERROR_CODE();
|
||||
mk_c(c)->reset_last_result();
|
||||
ast_manager& m = mk_c(c)->m();
|
||||
datatype_util dt_util(m);
|
||||
|
||||
sort_ref_vector sorts(m);
|
||||
sort* e;
|
||||
|
||||
ptr_vector<constructor_decl> constrs;
|
||||
for (unsigned i = 0; i < n; ++i) {
|
||||
symbol e_name(to_symbol(enum_names[i]));
|
||||
std::string recognizer_s("is_");
|
||||
recognizer_s += e_name.str();
|
||||
symbol recognizer(recognizer_s.c_str());
|
||||
|
||||
constrs.push_back(mk_constructor_decl(e_name, recognizer, 0, 0));
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
datatype_decl * dt = mk_datatype_decl(to_symbol(name), n, constrs.c_ptr());
|
||||
bool is_ok = mk_c(c)->get_dt_plugin()->mk_datatypes(1, &dt, sorts);
|
||||
del_datatype_decl(dt);
|
||||
|
||||
if (!is_ok) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
}
|
||||
|
||||
// create enum type.
|
||||
SASSERT(sorts.size() == 1);
|
||||
e = sorts[0].get();
|
||||
mk_c(c)->save_multiple_ast_trail(e);
|
||||
|
||||
// create constructor
|
||||
SASSERT(dt_util.is_datatype(e));
|
||||
SASSERT(!dt_util.is_recursive(e));
|
||||
ptr_vector<func_decl> const * decls = dt_util.get_datatype_constructors(e);
|
||||
SASSERT(decls && decls->size() == n);
|
||||
for (unsigned i = 0; i < n; ++i) {
|
||||
func_decl* decl = (*decls)[i];
|
||||
mk_c(c)->save_multiple_ast_trail(decl);
|
||||
enum_consts[i] = of_func_decl(decl);
|
||||
decl = dt_util.get_constructor_recognizer(decl);
|
||||
mk_c(c)->save_multiple_ast_trail(decl);
|
||||
enum_testers[i] = of_func_decl(decl);
|
||||
}
|
||||
|
||||
RETURN_Z3_mk_enumeration_sort(of_sort(e));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_sort Z3_API Z3_mk_list_sort(Z3_context c,
|
||||
Z3_symbol name,
|
||||
Z3_sort elem_sort,
|
||||
Z3_func_decl* nil_decl,
|
||||
Z3_func_decl* is_nil_decl,
|
||||
Z3_func_decl* cons_decl,
|
||||
Z3_func_decl* is_cons_decl,
|
||||
Z3_func_decl* head_decl,
|
||||
Z3_func_decl* tail_decl
|
||||
) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_list_sort(c, name, elem_sort, nil_decl, is_nil_decl, cons_decl, is_cons_decl, head_decl, tail_decl);
|
||||
RESET_ERROR_CODE();
|
||||
ast_manager& m = mk_c(c)->m();
|
||||
mk_c(c)->reset_last_result();
|
||||
datatype_util data_util(m);
|
||||
accessor_decl* head_tail[2] = {
|
||||
mk_accessor_decl(symbol("head"), type_ref(to_sort(elem_sort))),
|
||||
mk_accessor_decl(symbol("tail"), type_ref(0))
|
||||
};
|
||||
constructor_decl* constrs[2] = {
|
||||
mk_constructor_decl(symbol("nil"), symbol("is_nil"), 0, 0),
|
||||
// Leo: SMT 2.0 document uses 'insert' instead of cons
|
||||
mk_constructor_decl(symbol("cons"), symbol("is_cons"), 2, head_tail)
|
||||
};
|
||||
|
||||
sort_ref_vector sorts(m);
|
||||
{
|
||||
datatype_decl * decl = mk_datatype_decl(to_symbol(name), 2, constrs);
|
||||
bool is_ok = mk_c(c)->get_dt_plugin()->mk_datatypes(1, &decl, sorts);
|
||||
del_datatype_decl(decl);
|
||||
|
||||
if (!is_ok) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
}
|
||||
sort * s = sorts.get(0);
|
||||
|
||||
mk_c(c)->save_multiple_ast_trail(s);
|
||||
ptr_vector<func_decl> const& cnstrs = *data_util.get_datatype_constructors(s);
|
||||
SASSERT(cnstrs.size() == 2);
|
||||
func_decl* f;
|
||||
if (nil_decl) {
|
||||
f = cnstrs[0];
|
||||
mk_c(c)->save_multiple_ast_trail(f);
|
||||
*nil_decl = of_func_decl(f);
|
||||
}
|
||||
if (is_nil_decl) {
|
||||
f = data_util.get_constructor_recognizer(cnstrs[0]);
|
||||
mk_c(c)->save_multiple_ast_trail(f);
|
||||
*is_nil_decl = of_func_decl(f);
|
||||
}
|
||||
if (cons_decl) {
|
||||
f = cnstrs[1];
|
||||
mk_c(c)->save_multiple_ast_trail(f);
|
||||
*cons_decl = of_func_decl(f);
|
||||
}
|
||||
if (is_cons_decl) {
|
||||
f = data_util.get_constructor_recognizer(cnstrs[1]);
|
||||
mk_c(c)->save_multiple_ast_trail(f);
|
||||
*is_cons_decl = of_func_decl(f);
|
||||
}
|
||||
if (head_decl) {
|
||||
ptr_vector<func_decl> const* acc = data_util.get_constructor_accessors(cnstrs[1]);
|
||||
SASSERT(acc);
|
||||
SASSERT(acc->size() == 2);
|
||||
f = (*acc)[0];
|
||||
mk_c(c)->save_multiple_ast_trail(f);
|
||||
*head_decl = of_func_decl(f);
|
||||
}
|
||||
if (tail_decl) {
|
||||
ptr_vector<func_decl> const* acc = data_util.get_constructor_accessors(cnstrs[1]);
|
||||
SASSERT(acc);
|
||||
SASSERT(acc->size() == 2);
|
||||
f = (*acc)[1];
|
||||
mk_c(c)->save_multiple_ast_trail(f);
|
||||
*tail_decl = of_func_decl(f);
|
||||
}
|
||||
RETURN_Z3_mk_list_sort(of_sort(s));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
struct constructor {
|
||||
symbol m_name;
|
||||
symbol m_tester;
|
||||
svector<symbol> m_field_names;
|
||||
sort_ref_vector m_sorts;
|
||||
unsigned_vector m_sort_refs;
|
||||
func_decl_ref m_constructor;
|
||||
constructor(ast_manager& m) : m_sorts(m), m_constructor(m) {}
|
||||
};
|
||||
|
||||
Z3_constructor Z3_API Z3_mk_constructor(Z3_context c,
|
||||
Z3_symbol name,
|
||||
Z3_symbol tester,
|
||||
unsigned num_fields,
|
||||
Z3_symbol const field_names[],
|
||||
Z3_sort const sorts[],
|
||||
unsigned sort_refs[]
|
||||
) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_constructor(c, name, tester, num_fields, field_names, sorts, sort_refs);
|
||||
RESET_ERROR_CODE();
|
||||
ast_manager& m = mk_c(c)->m();
|
||||
constructor* cnstr = alloc(constructor, m);
|
||||
cnstr->m_name = to_symbol(name);
|
||||
cnstr->m_tester = to_symbol(tester);
|
||||
for (unsigned i = 0; i < num_fields; ++i) {
|
||||
cnstr->m_field_names.push_back(to_symbol(field_names[i]));
|
||||
cnstr->m_sorts.push_back(to_sort(sorts[i]));
|
||||
cnstr->m_sort_refs.push_back(sort_refs[i]);
|
||||
}
|
||||
RETURN_Z3(reinterpret_cast<Z3_constructor>(cnstr));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
|
||||
void Z3_API Z3_query_constructor(Z3_context c,
|
||||
Z3_constructor constr,
|
||||
unsigned num_fields,
|
||||
Z3_func_decl* constructor_decl,
|
||||
Z3_func_decl* tester,
|
||||
Z3_func_decl accessors[]) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_query_constructor(c, constr, num_fields, constructor_decl, tester, accessors);
|
||||
RESET_ERROR_CODE();
|
||||
mk_c(c)->reset_last_result();
|
||||
if (!constr) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
return;
|
||||
}
|
||||
ast_manager& m = mk_c(c)->m();
|
||||
datatype_util data_util(m);
|
||||
func_decl* f = reinterpret_cast<constructor*>(constr)->m_constructor.get();
|
||||
|
||||
if (!f) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
return;
|
||||
}
|
||||
if (constructor_decl) {
|
||||
mk_c(c)->save_multiple_ast_trail(f);
|
||||
*constructor_decl = of_func_decl(f);
|
||||
}
|
||||
if (tester) {
|
||||
func_decl* f2 = data_util.get_constructor_recognizer(f);
|
||||
mk_c(c)->save_multiple_ast_trail(f2);
|
||||
*tester = of_func_decl(f2);
|
||||
}
|
||||
|
||||
ptr_vector<func_decl> const* accs = data_util.get_constructor_accessors(f);
|
||||
if (!accs && num_fields > 0) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
return;
|
||||
}
|
||||
for (unsigned i = 0; i < num_fields; ++i) {
|
||||
func_decl* f2 = (*accs)[i];
|
||||
mk_c(c)->save_multiple_ast_trail(f2);
|
||||
accessors[i] = of_func_decl(f2);
|
||||
}
|
||||
RETURN_Z3_query_constructor;
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_del_constructor(Z3_context c, Z3_constructor constr) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_del_constructor(c, constr);
|
||||
RESET_ERROR_CODE();
|
||||
dealloc(reinterpret_cast<constructor*>(constr));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
static datatype_decl* mk_datatype_decl(Z3_context c,
|
||||
Z3_symbol name,
|
||||
unsigned num_constructors,
|
||||
Z3_constructor constructors[]) {
|
||||
ptr_vector<constructor_decl> constrs;
|
||||
for (unsigned i = 0; i < num_constructors; ++i) {
|
||||
constructor* cn = reinterpret_cast<constructor*>(constructors[i]);
|
||||
ptr_vector<accessor_decl> acc;
|
||||
for (unsigned j = 0; j < cn->m_sorts.size(); ++j) {
|
||||
if (cn->m_sorts[j].get()) {
|
||||
acc.push_back(mk_accessor_decl(cn->m_field_names[j], type_ref(cn->m_sorts[j].get())));
|
||||
}
|
||||
else {
|
||||
acc.push_back(mk_accessor_decl(cn->m_field_names[j], type_ref(cn->m_sort_refs[j])));
|
||||
}
|
||||
}
|
||||
constrs.push_back(mk_constructor_decl(cn->m_name, cn->m_tester, acc.size(), acc.c_ptr()));
|
||||
}
|
||||
return mk_datatype_decl(to_symbol(name), num_constructors, constrs.c_ptr());
|
||||
}
|
||||
|
||||
Z3_sort Z3_API Z3_mk_datatype(Z3_context c,
|
||||
Z3_symbol name,
|
||||
unsigned num_constructors,
|
||||
Z3_constructor constructors[]) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_datatype(c, name, num_constructors, constructors);
|
||||
RESET_ERROR_CODE();
|
||||
ast_manager& m = mk_c(c)->m();
|
||||
datatype_util data_util(m);
|
||||
|
||||
sort_ref_vector sorts(m);
|
||||
{
|
||||
datatype_decl * data = mk_datatype_decl(c, name, num_constructors, constructors);
|
||||
bool is_ok = mk_c(c)->get_dt_plugin()->mk_datatypes(1, &data, sorts);
|
||||
del_datatype_decl(data);
|
||||
|
||||
if (!is_ok) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
}
|
||||
sort * s = sorts.get(0);
|
||||
|
||||
mk_c(c)->save_ast_trail(s);
|
||||
ptr_vector<func_decl> const* cnstrs = data_util.get_datatype_constructors(s);
|
||||
|
||||
for (unsigned i = 0; i < num_constructors; ++i) {
|
||||
constructor* cn = reinterpret_cast<constructor*>(constructors[i]);
|
||||
cn->m_constructor = (*cnstrs)[i];
|
||||
}
|
||||
RETURN_Z3_mk_datatype(of_sort(s));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
typedef ptr_vector<constructor> constructor_list;
|
||||
|
||||
Z3_constructor_list Z3_API Z3_mk_constructor_list(Z3_context c,
|
||||
unsigned num_constructors,
|
||||
Z3_constructor const constructors[]) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_constructor_list(c, num_constructors, constructors);
|
||||
RESET_ERROR_CODE();
|
||||
constructor_list* result = alloc(ptr_vector<constructor>);
|
||||
for (unsigned i = 0; i < num_constructors; ++i) {
|
||||
result->push_back(reinterpret_cast<constructor*>(constructors[i]));
|
||||
}
|
||||
RETURN_Z3(reinterpret_cast<Z3_constructor_list>(result));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
void Z3_API Z3_del_constructor_list(Z3_context c, Z3_constructor_list clist) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_del_constructor_list(c, clist);
|
||||
RESET_ERROR_CODE();
|
||||
dealloc(reinterpret_cast<constructor_list*>(clist));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_mk_datatypes(Z3_context c,
|
||||
unsigned num_sorts,
|
||||
Z3_symbol const sort_names[],
|
||||
Z3_sort sorts[],
|
||||
Z3_constructor_list constructor_lists[]) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_datatypes(c, num_sorts, sort_names, sorts, constructor_lists);
|
||||
RESET_ERROR_CODE();
|
||||
ast_manager& m = mk_c(c)->m();
|
||||
mk_c(c)->reset_last_result();
|
||||
datatype_util data_util(m);
|
||||
|
||||
ptr_vector<datatype_decl> datas;
|
||||
for (unsigned i = 0; i < num_sorts; ++i) {
|
||||
constructor_list* cl = reinterpret_cast<constructor_list*>(constructor_lists[i]);
|
||||
datas.push_back(mk_datatype_decl(c,sort_names[i], cl->size(), reinterpret_cast<Z3_constructor*>(cl->c_ptr())));
|
||||
}
|
||||
sort_ref_vector _sorts(m);
|
||||
bool ok = mk_c(c)->get_dt_plugin()->mk_datatypes(datas.size(), datas.c_ptr(), _sorts);
|
||||
del_datatype_decls(datas.size(), datas.c_ptr());
|
||||
|
||||
if (!ok) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
return;
|
||||
}
|
||||
|
||||
SASSERT(_sorts.size() == num_sorts);
|
||||
for (unsigned i = 0; i < _sorts.size(); ++i) {
|
||||
sort* s = _sorts[i].get();
|
||||
mk_c(c)->save_multiple_ast_trail(s);
|
||||
sorts[i] = of_sort(s);
|
||||
constructor_list* cl = reinterpret_cast<constructor_list*>(constructor_lists[i]);
|
||||
ptr_vector<func_decl> const* cnstrs = data_util.get_datatype_constructors(s);
|
||||
for (unsigned j = 0; j < cl->size(); ++j) {
|
||||
constructor* cn = (*cl)[j];
|
||||
cn->m_constructor = (*cnstrs)[j];
|
||||
}
|
||||
}
|
||||
RETURN_Z3_mk_datatypes;
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
unsigned Z3_API Z3_get_datatype_sort_num_constructors(Z3_context c, Z3_sort t) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_datatype_sort_num_constructors(c, t);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_VALID_AST(t, 0);
|
||||
sort * _t = to_sort(t);
|
||||
datatype_util dt_util(mk_c(c)->m());
|
||||
|
||||
if (!dt_util.is_datatype(_t)) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
return 0;
|
||||
}
|
||||
ptr_vector<func_decl> const * decls = dt_util.get_datatype_constructors(_t);
|
||||
if (!decls) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
return 0;
|
||||
}
|
||||
return decls->size();
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_func_decl get_datatype_sort_constructor_core(Z3_context c, Z3_sort t, unsigned idx) {
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_VALID_AST(t, 0);
|
||||
sort * _t = to_sort(t);
|
||||
datatype_util dt_util(mk_c(c)->m());
|
||||
if (!dt_util.is_datatype(_t)) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
return 0;
|
||||
}
|
||||
ptr_vector<func_decl> const * decls = dt_util.get_datatype_constructors(_t);
|
||||
if (!decls || idx >= decls->size()) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
return 0;
|
||||
}
|
||||
func_decl* decl = (*decls)[idx];
|
||||
mk_c(c)->save_ast_trail(decl);
|
||||
return of_func_decl(decl);
|
||||
}
|
||||
|
||||
Z3_func_decl Z3_API Z3_get_datatype_sort_constructor(Z3_context c, Z3_sort t, unsigned idx) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_datatype_sort_constructor(c, t, idx);
|
||||
RESET_ERROR_CODE();
|
||||
Z3_func_decl r = get_datatype_sort_constructor_core(c, t, idx);
|
||||
RETURN_Z3(r);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_func_decl Z3_API Z3_get_datatype_sort_recognizer(Z3_context c, Z3_sort t, unsigned idx) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_datatype_sort_recognizer(c, t, idx);
|
||||
RESET_ERROR_CODE();
|
||||
sort * _t = to_sort(t);
|
||||
datatype_util dt_util(mk_c(c)->m());
|
||||
|
||||
if (!dt_util.is_datatype(_t)) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
ptr_vector<func_decl> const * decls = dt_util.get_datatype_constructors(_t);
|
||||
if (!decls || idx >= decls->size()) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
func_decl* decl = (*decls)[idx];
|
||||
decl = dt_util.get_constructor_recognizer(decl);
|
||||
mk_c(c)->save_ast_trail(decl);
|
||||
RETURN_Z3(of_func_decl(decl));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_func_decl Z3_API Z3_get_datatype_sort_constructor_accessor(Z3_context c, Z3_sort t, unsigned idx_c, unsigned idx_a) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_datatype_sort_constructor_accessor(c, t, idx_c, idx_a);
|
||||
RESET_ERROR_CODE();
|
||||
sort * _t = to_sort(t);
|
||||
datatype_util dt_util(mk_c(c)->m());
|
||||
|
||||
if (!dt_util.is_datatype(_t)) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
ptr_vector<func_decl> const * decls = dt_util.get_datatype_constructors(_t);
|
||||
if (!decls || idx_c >= decls->size()) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
func_decl* decl = (*decls)[idx_c];
|
||||
if (decl->get_arity() <= idx_a) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
ptr_vector<func_decl> const * accs = dt_util.get_constructor_accessors(decl);
|
||||
SASSERT(accs && accs->size() == decl->get_arity());
|
||||
if (!accs || accs->size() <= idx_a) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
decl = (*accs)[idx_a];
|
||||
mk_c(c)->save_ast_trail(decl);
|
||||
RETURN_Z3(of_func_decl(decl));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_func_decl Z3_API Z3_get_tuple_sort_mk_decl(Z3_context c, Z3_sort t) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_tuple_sort_mk_decl(c, t);
|
||||
RESET_ERROR_CODE();
|
||||
sort * tuple = to_sort(t);
|
||||
datatype_util dt_util(mk_c(c)->m());
|
||||
if (!dt_util.is_datatype(tuple) || dt_util.is_recursive(tuple) || dt_util.get_datatype_num_constructors(tuple) != 1) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
Z3_func_decl r = get_datatype_sort_constructor_core(c, t, 0);
|
||||
RETURN_Z3(r);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
unsigned Z3_API Z3_get_tuple_sort_num_fields(Z3_context c, Z3_sort t) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_tuple_sort_num_fields(c, t);
|
||||
RESET_ERROR_CODE();
|
||||
sort * tuple = to_sort(t);
|
||||
datatype_util dt_util(mk_c(c)->m());
|
||||
if (!dt_util.is_datatype(tuple) || dt_util.is_recursive(tuple) || dt_util.get_datatype_num_constructors(tuple) != 1) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
return 0;
|
||||
}
|
||||
ptr_vector<func_decl> const * decls = dt_util.get_datatype_constructors(tuple);
|
||||
if (!decls || decls->size() != 1) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
return 0;
|
||||
}
|
||||
ptr_vector<func_decl> const * accs = dt_util.get_constructor_accessors((*decls)[0]);
|
||||
if (!accs) {
|
||||
return 0;
|
||||
}
|
||||
return accs->size();
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_func_decl Z3_API Z3_get_tuple_sort_field_decl(Z3_context c, Z3_sort t, unsigned i) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_tuple_sort_field_decl(c, t, i);
|
||||
RESET_ERROR_CODE();
|
||||
sort * tuple = to_sort(t);
|
||||
datatype_util dt_util(mk_c(c)->m());
|
||||
if (!dt_util.is_datatype(tuple) || dt_util.is_recursive(tuple) || dt_util.get_datatype_num_constructors(tuple) != 1) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
ptr_vector<func_decl> const * decls = dt_util.get_datatype_constructors(tuple);
|
||||
if (!decls || decls->size() != 1) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
ptr_vector<func_decl> const * accs = dt_util.get_constructor_accessors((*decls)[0]);
|
||||
if (!accs) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
if (accs->size() <= i) {
|
||||
SET_ERROR_CODE(Z3_IOB);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
func_decl* acc = (*accs)[i];
|
||||
mk_c(c)->save_ast_trail(acc);
|
||||
RETURN_Z3(of_func_decl(acc));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
};
|
181
lib/api_goal.cpp
Normal file
181
lib/api_goal.cpp
Normal file
|
@ -0,0 +1,181 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
api_goal.cpp
|
||||
|
||||
Abstract:
|
||||
API for creating goals
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2012-03-06.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include<iostream>
|
||||
#include"z3.h"
|
||||
#include"api_log_macros.h"
|
||||
#include"api_context.h"
|
||||
#include"api_goal.h"
|
||||
#include"ast_translation.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
Z3_goal Z3_API Z3_mk_goal(Z3_context c, Z3_bool models, Z3_bool unsat_cores, Z3_bool proofs) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_goal(c, models, unsat_cores, proofs);
|
||||
RESET_ERROR_CODE();
|
||||
if (proofs != 0 && !mk_c(c)->m().proofs_enabled()) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
Z3_goal_ref * g = alloc(Z3_goal_ref);
|
||||
g->m_goal = alloc(goal, mk_c(c)->m(), proofs != 0, models != 0, unsat_cores != 0);
|
||||
mk_c(c)->save_object(g);
|
||||
Z3_goal r = of_goal(g);
|
||||
RETURN_Z3(r);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
void Z3_API Z3_goal_inc_ref(Z3_context c, Z3_goal g) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_goal_inc_ref(c, g);
|
||||
RESET_ERROR_CODE();
|
||||
to_goal(g)->inc_ref();
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_goal_dec_ref(Z3_context c, Z3_goal g) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_goal_dec_ref(c, g);
|
||||
RESET_ERROR_CODE();
|
||||
to_goal(g)->dec_ref();
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
Z3_goal_prec Z3_API Z3_goal_precision(Z3_context c, Z3_goal g) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_goal_precision(c, g);
|
||||
RESET_ERROR_CODE();
|
||||
switch (to_goal_ref(g)->prec()) {
|
||||
case goal::PRECISE: return Z3_GOAL_PRECISE;
|
||||
case goal::UNDER: return Z3_GOAL_UNDER;
|
||||
case goal::OVER: return Z3_GOAL_OVER;
|
||||
case goal::UNDER_OVER: return Z3_GOAL_UNDER_OVER;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return Z3_GOAL_UNDER_OVER;
|
||||
}
|
||||
Z3_CATCH_RETURN(Z3_GOAL_UNDER_OVER);
|
||||
}
|
||||
|
||||
void Z3_API Z3_goal_assert(Z3_context c, Z3_goal g, Z3_ast a) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_goal_assert(c, g, a);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_FORMULA(a,);
|
||||
to_goal_ref(g)->assert_expr(to_expr(a));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
Z3_bool Z3_API Z3_goal_inconsistent(Z3_context c, Z3_goal g) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_goal_inconsistent(c, g);
|
||||
RESET_ERROR_CODE();
|
||||
return to_goal_ref(g)->inconsistent();
|
||||
Z3_CATCH_RETURN(Z3_FALSE);
|
||||
}
|
||||
|
||||
unsigned Z3_API Z3_goal_depth(Z3_context c, Z3_goal g) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_goal_depth(c, g);
|
||||
RESET_ERROR_CODE();
|
||||
return to_goal_ref(g)->depth();
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
void Z3_API Z3_goal_reset(Z3_context c, Z3_goal g) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_goal_reset(c, g);
|
||||
RESET_ERROR_CODE();
|
||||
to_goal_ref(g)->reset();
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
unsigned Z3_API Z3_goal_size(Z3_context c, Z3_goal g) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_goal_size(c, g);
|
||||
RESET_ERROR_CODE();
|
||||
return to_goal_ref(g)->size();
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_goal_formula(Z3_context c, Z3_goal g, unsigned idx) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_goal_formula(c, g, idx);
|
||||
RESET_ERROR_CODE();
|
||||
if (idx >= to_goal_ref(g)->size()) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
expr * result = to_goal_ref(g)->form(idx);
|
||||
mk_c(c)->save_ast_trail(result);
|
||||
RETURN_Z3(of_ast(result));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
unsigned Z3_API Z3_goal_num_exprs(Z3_context c, Z3_goal g) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_goal_num_exprs(c, g);
|
||||
RESET_ERROR_CODE();
|
||||
return to_goal_ref(g)->num_exprs();
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_bool Z3_API Z3_goal_is_decided_sat(Z3_context c, Z3_goal g) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_goal_is_decided_sat(c, g);
|
||||
RESET_ERROR_CODE();
|
||||
return to_goal_ref(g)->is_decided_sat();
|
||||
Z3_CATCH_RETURN(Z3_FALSE);
|
||||
}
|
||||
|
||||
Z3_bool Z3_API Z3_goal_is_decided_unsat(Z3_context c, Z3_goal g) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_goal_is_decided_unsat(c, g);
|
||||
RESET_ERROR_CODE();
|
||||
return to_goal_ref(g)->is_decided_unsat();
|
||||
Z3_CATCH_RETURN(Z3_FALSE);
|
||||
}
|
||||
|
||||
Z3_goal Z3_API Z3_goal_translate(Z3_context c, Z3_goal g, Z3_context target) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_goal_translate(c, g, target);
|
||||
RESET_ERROR_CODE();
|
||||
ast_translation translator(mk_c(c)->m(), mk_c(target)->m());
|
||||
Z3_goal_ref * _r = alloc(Z3_goal_ref);
|
||||
_r->m_goal = to_goal_ref(g)->translate(translator);
|
||||
mk_c(target)->save_object(_r);
|
||||
Z3_goal r = of_goal(_r);
|
||||
RETURN_Z3(r);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_string Z3_API Z3_goal_to_string(Z3_context c, Z3_goal g) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_goal_to_string(c, g);
|
||||
RESET_ERROR_CODE();
|
||||
std::ostringstream buffer;
|
||||
to_goal_ref(g)->display(buffer);
|
||||
// Hack for removing the trailing '\n'
|
||||
std::string result = buffer.str();
|
||||
SASSERT(result.size() > 0);
|
||||
result.resize(result.size()-1);
|
||||
return mk_c(c)->mk_external_string(result);
|
||||
Z3_CATCH_RETURN("");
|
||||
}
|
||||
|
||||
};
|
33
lib/api_goal.h
Normal file
33
lib/api_goal.h
Normal file
|
@ -0,0 +1,33 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
api_goal.h
|
||||
|
||||
Abstract:
|
||||
API for creating goals
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2012-03-06.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _API_GOAL_H_
|
||||
#define _API_GOAL_H_
|
||||
|
||||
#include"api_util.h"
|
||||
#include"goal.h"
|
||||
|
||||
struct Z3_goal_ref : public api::object {
|
||||
goal_ref m_goal;
|
||||
virtual ~Z3_goal_ref() {}
|
||||
};
|
||||
|
||||
inline Z3_goal_ref * to_goal(Z3_goal g) { return reinterpret_cast<Z3_goal_ref *>(g); }
|
||||
inline Z3_goal of_goal(Z3_goal_ref * g) { return reinterpret_cast<Z3_goal>(g); }
|
||||
inline goal_ref to_goal_ref(Z3_goal g) { return g == 0 ? goal_ref() : to_goal(g)->m_goal; }
|
||||
|
||||
#endif
|
54
lib/api_log.cpp
Normal file
54
lib/api_log.cpp
Normal file
|
@ -0,0 +1,54 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
api_log.cpp
|
||||
|
||||
Abstract:
|
||||
API for creating logs
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2012-02-29.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include<iostream>
|
||||
#include<fstream>
|
||||
#include"z3.h"
|
||||
#include"api_log_macros.h"
|
||||
#include"util.h"
|
||||
|
||||
std::ostream * g_z3_log = 0;
|
||||
bool g_z3_log_enabled = false;
|
||||
|
||||
extern "C" {
|
||||
Z3_bool Z3_API Z3_open_log(Z3_string filename) {
|
||||
if (g_z3_log != 0)
|
||||
Z3_close_log();
|
||||
g_z3_log = alloc(std::ofstream, filename);
|
||||
g_z3_log_enabled = true;
|
||||
if (g_z3_log->bad() || g_z3_log->fail()) {
|
||||
dealloc(g_z3_log);
|
||||
g_z3_log = 0;
|
||||
return Z3_FALSE;
|
||||
}
|
||||
return Z3_TRUE;
|
||||
}
|
||||
|
||||
void Z3_API Z3_append_log(Z3_string str) {
|
||||
if (g_z3_log == 0)
|
||||
return;
|
||||
_Z3_append_log(static_cast<char const *>(str));
|
||||
}
|
||||
|
||||
void Z3_API Z3_close_log() {
|
||||
if (g_z3_log != 0) {
|
||||
dealloc(g_z3_log);
|
||||
g_z3_log_enabled = false;
|
||||
g_z3_log = 0;
|
||||
}
|
||||
}
|
||||
}
|
3311
lib/api_log_macros.cpp
Normal file
3311
lib/api_log_macros.cpp
Normal file
File diff suppressed because it is too large
Load diff
975
lib/api_log_macros.h
Normal file
975
lib/api_log_macros.h
Normal file
|
@ -0,0 +1,975 @@
|
|||
// Automatically generated file, generator: api.py
|
||||
#include"z3.h"
|
||||
extern std::ostream * g_z3_log;
|
||||
extern bool g_z3_log_enabled;
|
||||
class z3_log_ctx { bool m_prev; public: z3_log_ctx():m_prev(g_z3_log_enabled) { g_z3_log_enabled = false; } ~z3_log_ctx() { g_z3_log_enabled = m_prev; } bool enabled() const { return m_prev; } };
|
||||
inline void SetR(void * obj) { *g_z3_log << "= " << obj << "\n"; }
|
||||
inline void SetO(void * obj, unsigned pos) { *g_z3_log << "* " << obj << " " << pos << "\n"; }
|
||||
inline void SetAO(void * obj, unsigned pos, unsigned idx) { *g_z3_log << "@ " << obj << " " << pos << " " << idx << "\n"; }
|
||||
#define RETURN_Z3(Z3RES) if (_LOG_CTX.enabled()) { SetR(Z3RES); } return Z3RES
|
||||
void _Z3_append_log(char const * msg);
|
||||
void log_Z3_mk_config();
|
||||
#define LOG_Z3_mk_config() z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_config(); }
|
||||
void log_Z3_del_config(Z3_config a0);
|
||||
#define LOG_Z3_del_config(_ARG0) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_del_config(_ARG0); }
|
||||
void log_Z3_set_param_value(Z3_config a0, Z3_string a1, Z3_string a2);
|
||||
#define LOG_Z3_set_param_value(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_set_param_value(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_context(Z3_config a0);
|
||||
#define LOG_Z3_mk_context(_ARG0) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_context(_ARG0); }
|
||||
void log_Z3_mk_context_rc(Z3_config a0);
|
||||
#define LOG_Z3_mk_context_rc(_ARG0) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_context_rc(_ARG0); }
|
||||
void log_Z3_set_logic(Z3_context a0, Z3_string a1);
|
||||
#define LOG_Z3_set_logic(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_set_logic(_ARG0, _ARG1); }
|
||||
void log_Z3_del_context(Z3_context a0);
|
||||
#define LOG_Z3_del_context(_ARG0) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_del_context(_ARG0); }
|
||||
void log_Z3_inc_ref(Z3_context a0, Z3_ast a1);
|
||||
#define LOG_Z3_inc_ref(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_inc_ref(_ARG0, _ARG1); }
|
||||
void log_Z3_dec_ref(Z3_context a0, Z3_ast a1);
|
||||
#define LOG_Z3_dec_ref(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_dec_ref(_ARG0, _ARG1); }
|
||||
void log_Z3_toggle_warning_messages(Z3_bool a0);
|
||||
#define LOG_Z3_toggle_warning_messages(_ARG0) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_toggle_warning_messages(_ARG0); }
|
||||
void log_Z3_update_param_value(Z3_context a0, Z3_string a1, Z3_string a2);
|
||||
#define LOG_Z3_update_param_value(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_update_param_value(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_get_param_value(Z3_context a0, Z3_string a1, Z3_string* a2);
|
||||
#define LOG_Z3_get_param_value(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_param_value(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_int_symbol(Z3_context a0, int a1);
|
||||
#define LOG_Z3_mk_int_symbol(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_int_symbol(_ARG0, _ARG1); }
|
||||
void log_Z3_mk_string_symbol(Z3_context a0, Z3_string a1);
|
||||
#define LOG_Z3_mk_string_symbol(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_string_symbol(_ARG0, _ARG1); }
|
||||
void log_Z3_is_eq_sort(Z3_context a0, Z3_sort a1, Z3_sort a2);
|
||||
#define LOG_Z3_is_eq_sort(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_is_eq_sort(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_uninterpreted_sort(Z3_context a0, Z3_symbol a1);
|
||||
#define LOG_Z3_mk_uninterpreted_sort(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_uninterpreted_sort(_ARG0, _ARG1); }
|
||||
void log_Z3_mk_bool_sort(Z3_context a0);
|
||||
#define LOG_Z3_mk_bool_sort(_ARG0) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_bool_sort(_ARG0); }
|
||||
void log_Z3_mk_int_sort(Z3_context a0);
|
||||
#define LOG_Z3_mk_int_sort(_ARG0) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_int_sort(_ARG0); }
|
||||
void log_Z3_mk_real_sort(Z3_context a0);
|
||||
#define LOG_Z3_mk_real_sort(_ARG0) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_real_sort(_ARG0); }
|
||||
void log_Z3_mk_bv_sort(Z3_context a0, unsigned a1);
|
||||
#define LOG_Z3_mk_bv_sort(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_bv_sort(_ARG0, _ARG1); }
|
||||
void log_Z3_mk_array_sort(Z3_context a0, Z3_sort a1, Z3_sort a2);
|
||||
#define LOG_Z3_mk_array_sort(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_array_sort(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_tuple_sort(Z3_context a0, Z3_symbol a1, unsigned a2, Z3_symbol const * a3, Z3_sort const * a4, Z3_func_decl* a5, Z3_func_decl* a6);
|
||||
#define LOG_Z3_mk_tuple_sort(_ARG0, _ARG1, _ARG2, _ARG3, _ARG4, _ARG5, _ARG6) z3_log_ctx _LOG_CTX; Z3_func_decl* Z3ARG5; unsigned Z3ARG2; Z3_func_decl* Z3ARG6; if (_LOG_CTX.enabled()) { log_Z3_mk_tuple_sort(_ARG0, _ARG1, _ARG2, _ARG3, _ARG4, _ARG5, _ARG6); Z3ARG5 = _ARG5; Z3ARG2 = _ARG2; Z3ARG6 = _ARG6; }
|
||||
#define RETURN_Z3_mk_tuple_sort(Z3RES) if (_LOG_CTX.enabled()) { SetR(Z3RES); SetO((Z3ARG5 == 0 ? 0 : *Z3ARG5), 5); for (unsigned i = 0; i < Z3ARG2; i++) { SetAO(Z3ARG6[i], 6, i); } } return Z3RES
|
||||
void log_Z3_mk_enumeration_sort(Z3_context a0, Z3_symbol a1, unsigned a2, Z3_symbol const * a3, Z3_func_decl* a4, Z3_func_decl* a5);
|
||||
#define LOG_Z3_mk_enumeration_sort(_ARG0, _ARG1, _ARG2, _ARG3, _ARG4, _ARG5) z3_log_ctx _LOG_CTX; unsigned Z3ARG2; Z3_func_decl* Z3ARG4; Z3_func_decl* Z3ARG5; if (_LOG_CTX.enabled()) { log_Z3_mk_enumeration_sort(_ARG0, _ARG1, _ARG2, _ARG3, _ARG4, _ARG5); Z3ARG2 = _ARG2; Z3ARG4 = _ARG4; Z3ARG5 = _ARG5; }
|
||||
#define RETURN_Z3_mk_enumeration_sort(Z3RES) if (_LOG_CTX.enabled()) { SetR(Z3RES); for (unsigned i = 0; i < Z3ARG2; i++) { SetAO(Z3ARG4[i], 4, i); } for (unsigned i = 0; i < Z3ARG2; i++) { SetAO(Z3ARG5[i], 5, i); } } return Z3RES
|
||||
void log_Z3_mk_list_sort(Z3_context a0, Z3_symbol a1, Z3_sort a2, Z3_func_decl* a3, Z3_func_decl* a4, Z3_func_decl* a5, Z3_func_decl* a6, Z3_func_decl* a7, Z3_func_decl* a8);
|
||||
#define LOG_Z3_mk_list_sort(_ARG0, _ARG1, _ARG2, _ARG3, _ARG4, _ARG5, _ARG6, _ARG7, _ARG8) z3_log_ctx _LOG_CTX; Z3_func_decl* Z3ARG3; Z3_func_decl* Z3ARG4; Z3_func_decl* Z3ARG5; Z3_func_decl* Z3ARG6; Z3_func_decl* Z3ARG7; Z3_func_decl* Z3ARG8; if (_LOG_CTX.enabled()) { log_Z3_mk_list_sort(_ARG0, _ARG1, _ARG2, _ARG3, _ARG4, _ARG5, _ARG6, _ARG7, _ARG8); Z3ARG3 = _ARG3; Z3ARG4 = _ARG4; Z3ARG5 = _ARG5; Z3ARG6 = _ARG6; Z3ARG7 = _ARG7; Z3ARG8 = _ARG8; }
|
||||
#define RETURN_Z3_mk_list_sort(Z3RES) if (_LOG_CTX.enabled()) { SetR(Z3RES); SetO((Z3ARG3 == 0 ? 0 : *Z3ARG3), 3); SetO((Z3ARG4 == 0 ? 0 : *Z3ARG4), 4); SetO((Z3ARG5 == 0 ? 0 : *Z3ARG5), 5); SetO((Z3ARG6 == 0 ? 0 : *Z3ARG6), 6); SetO((Z3ARG7 == 0 ? 0 : *Z3ARG7), 7); SetO((Z3ARG8 == 0 ? 0 : *Z3ARG8), 8); } return Z3RES
|
||||
void log_Z3_mk_constructor(Z3_context a0, Z3_symbol a1, Z3_symbol a2, unsigned a3, Z3_symbol const * a4, Z3_sort const * a5, unsigned const * a6);
|
||||
#define LOG_Z3_mk_constructor(_ARG0, _ARG1, _ARG2, _ARG3, _ARG4, _ARG5, _ARG6) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_constructor(_ARG0, _ARG1, _ARG2, _ARG3, _ARG4, _ARG5, _ARG6); }
|
||||
void log_Z3_query_constructor(Z3_context a0, Z3_constructor a1, unsigned a2, Z3_func_decl* a3, Z3_func_decl* a4, Z3_func_decl* a5);
|
||||
#define LOG_Z3_query_constructor(_ARG0, _ARG1, _ARG2, _ARG3, _ARG4, _ARG5) z3_log_ctx _LOG_CTX; Z3_func_decl* Z3ARG3; Z3_func_decl* Z3ARG4; unsigned Z3ARG2; Z3_func_decl* Z3ARG5; if (_LOG_CTX.enabled()) { log_Z3_query_constructor(_ARG0, _ARG1, _ARG2, _ARG3, _ARG4, _ARG5); Z3ARG3 = _ARG3; Z3ARG4 = _ARG4; Z3ARG2 = _ARG2; Z3ARG5 = _ARG5; }
|
||||
#define RETURN_Z3_query_constructor if (_LOG_CTX.enabled()) { SetO((Z3ARG3 == 0 ? 0 : *Z3ARG3), 3); SetO((Z3ARG4 == 0 ? 0 : *Z3ARG4), 4); for (unsigned i = 0; i < Z3ARG2; i++) { SetAO(Z3ARG5[i], 5, i); } } return
|
||||
void log_Z3_del_constructor(Z3_context a0, Z3_constructor a1);
|
||||
#define LOG_Z3_del_constructor(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_del_constructor(_ARG0, _ARG1); }
|
||||
void log_Z3_mk_datatype(Z3_context a0, Z3_symbol a1, unsigned a2, Z3_constructor* a3);
|
||||
#define LOG_Z3_mk_datatype(_ARG0, _ARG1, _ARG2, _ARG3) z3_log_ctx _LOG_CTX; unsigned Z3ARG2; Z3_constructor* Z3ARG3; if (_LOG_CTX.enabled()) { log_Z3_mk_datatype(_ARG0, _ARG1, _ARG2, _ARG3); Z3ARG2 = _ARG2; Z3ARG3 = _ARG3; }
|
||||
#define RETURN_Z3_mk_datatype(Z3RES) if (_LOG_CTX.enabled()) { SetR(Z3RES); for (unsigned i = 0; i < Z3ARG2; i++) { SetAO(Z3ARG3[i], 3, i); } } return Z3RES
|
||||
void log_Z3_mk_constructor_list(Z3_context a0, unsigned a1, Z3_constructor const * a2);
|
||||
#define LOG_Z3_mk_constructor_list(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_constructor_list(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_del_constructor_list(Z3_context a0, Z3_constructor_list a1);
|
||||
#define LOG_Z3_del_constructor_list(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_del_constructor_list(_ARG0, _ARG1); }
|
||||
void log_Z3_mk_datatypes(Z3_context a0, unsigned a1, Z3_symbol const * a2, Z3_sort* a3, Z3_constructor_list* a4);
|
||||
#define LOG_Z3_mk_datatypes(_ARG0, _ARG1, _ARG2, _ARG3, _ARG4) z3_log_ctx _LOG_CTX; unsigned Z3ARG1; Z3_sort* Z3ARG3; Z3_constructor_list* Z3ARG4; if (_LOG_CTX.enabled()) { log_Z3_mk_datatypes(_ARG0, _ARG1, _ARG2, _ARG3, _ARG4); Z3ARG1 = _ARG1; Z3ARG3 = _ARG3; Z3ARG4 = _ARG4; }
|
||||
#define RETURN_Z3_mk_datatypes if (_LOG_CTX.enabled()) { for (unsigned i = 0; i < Z3ARG1; i++) { SetAO(Z3ARG3[i], 3, i); } for (unsigned i = 0; i < Z3ARG1; i++) { SetAO(Z3ARG4[i], 4, i); } } return
|
||||
void log_Z3_is_eq_ast(Z3_context a0, Z3_ast a1, Z3_ast a2);
|
||||
#define LOG_Z3_is_eq_ast(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_is_eq_ast(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_is_eq_func_decl(Z3_context a0, Z3_func_decl a1, Z3_func_decl a2);
|
||||
#define LOG_Z3_is_eq_func_decl(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_is_eq_func_decl(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_func_decl(Z3_context a0, Z3_symbol a1, unsigned a2, Z3_sort const * a3, Z3_sort a4);
|
||||
#define LOG_Z3_mk_func_decl(_ARG0, _ARG1, _ARG2, _ARG3, _ARG4) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_func_decl(_ARG0, _ARG1, _ARG2, _ARG3, _ARG4); }
|
||||
void log_Z3_mk_app(Z3_context a0, Z3_func_decl a1, unsigned a2, Z3_ast const * a3);
|
||||
#define LOG_Z3_mk_app(_ARG0, _ARG1, _ARG2, _ARG3) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_app(_ARG0, _ARG1, _ARG2, _ARG3); }
|
||||
void log_Z3_mk_const(Z3_context a0, Z3_symbol a1, Z3_sort a2);
|
||||
#define LOG_Z3_mk_const(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_const(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_label(Z3_context a0, Z3_symbol a1, Z3_bool a2, Z3_ast a3);
|
||||
#define LOG_Z3_mk_label(_ARG0, _ARG1, _ARG2, _ARG3) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_label(_ARG0, _ARG1, _ARG2, _ARG3); }
|
||||
void log_Z3_mk_fresh_func_decl(Z3_context a0, Z3_string a1, unsigned a2, Z3_sort const * a3, Z3_sort a4);
|
||||
#define LOG_Z3_mk_fresh_func_decl(_ARG0, _ARG1, _ARG2, _ARG3, _ARG4) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_fresh_func_decl(_ARG0, _ARG1, _ARG2, _ARG3, _ARG4); }
|
||||
void log_Z3_mk_fresh_const(Z3_context a0, Z3_string a1, Z3_sort a2);
|
||||
#define LOG_Z3_mk_fresh_const(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_fresh_const(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_true(Z3_context a0);
|
||||
#define LOG_Z3_mk_true(_ARG0) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_true(_ARG0); }
|
||||
void log_Z3_mk_false(Z3_context a0);
|
||||
#define LOG_Z3_mk_false(_ARG0) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_false(_ARG0); }
|
||||
void log_Z3_mk_eq(Z3_context a0, Z3_ast a1, Z3_ast a2);
|
||||
#define LOG_Z3_mk_eq(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_eq(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_distinct(Z3_context a0, unsigned a1, Z3_ast const * a2);
|
||||
#define LOG_Z3_mk_distinct(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_distinct(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_not(Z3_context a0, Z3_ast a1);
|
||||
#define LOG_Z3_mk_not(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_not(_ARG0, _ARG1); }
|
||||
void log_Z3_mk_ite(Z3_context a0, Z3_ast a1, Z3_ast a2, Z3_ast a3);
|
||||
#define LOG_Z3_mk_ite(_ARG0, _ARG1, _ARG2, _ARG3) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_ite(_ARG0, _ARG1, _ARG2, _ARG3); }
|
||||
void log_Z3_mk_iff(Z3_context a0, Z3_ast a1, Z3_ast a2);
|
||||
#define LOG_Z3_mk_iff(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_iff(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_implies(Z3_context a0, Z3_ast a1, Z3_ast a2);
|
||||
#define LOG_Z3_mk_implies(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_implies(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_xor(Z3_context a0, Z3_ast a1, Z3_ast a2);
|
||||
#define LOG_Z3_mk_xor(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_xor(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_and(Z3_context a0, unsigned a1, Z3_ast const * a2);
|
||||
#define LOG_Z3_mk_and(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_and(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_or(Z3_context a0, unsigned a1, Z3_ast const * a2);
|
||||
#define LOG_Z3_mk_or(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_or(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_add(Z3_context a0, unsigned a1, Z3_ast const * a2);
|
||||
#define LOG_Z3_mk_add(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_add(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_mul(Z3_context a0, unsigned a1, Z3_ast const * a2);
|
||||
#define LOG_Z3_mk_mul(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_mul(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_sub(Z3_context a0, unsigned a1, Z3_ast const * a2);
|
||||
#define LOG_Z3_mk_sub(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_sub(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_unary_minus(Z3_context a0, Z3_ast a1);
|
||||
#define LOG_Z3_mk_unary_minus(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_unary_minus(_ARG0, _ARG1); }
|
||||
void log_Z3_mk_div(Z3_context a0, Z3_ast a1, Z3_ast a2);
|
||||
#define LOG_Z3_mk_div(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_div(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_mod(Z3_context a0, Z3_ast a1, Z3_ast a2);
|
||||
#define LOG_Z3_mk_mod(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_mod(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_rem(Z3_context a0, Z3_ast a1, Z3_ast a2);
|
||||
#define LOG_Z3_mk_rem(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_rem(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_power(Z3_context a0, Z3_ast a1, Z3_ast a2);
|
||||
#define LOG_Z3_mk_power(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_power(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_is_algebraic_number(Z3_context a0, Z3_ast a1);
|
||||
#define LOG_Z3_is_algebraic_number(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_is_algebraic_number(_ARG0, _ARG1); }
|
||||
void log_Z3_get_algebraic_number_lower(Z3_context a0, Z3_ast a1, unsigned a2);
|
||||
#define LOG_Z3_get_algebraic_number_lower(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_algebraic_number_lower(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_get_algebraic_number_upper(Z3_context a0, Z3_ast a1, unsigned a2);
|
||||
#define LOG_Z3_get_algebraic_number_upper(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_algebraic_number_upper(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_lt(Z3_context a0, Z3_ast a1, Z3_ast a2);
|
||||
#define LOG_Z3_mk_lt(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_lt(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_le(Z3_context a0, Z3_ast a1, Z3_ast a2);
|
||||
#define LOG_Z3_mk_le(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_le(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_gt(Z3_context a0, Z3_ast a1, Z3_ast a2);
|
||||
#define LOG_Z3_mk_gt(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_gt(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_ge(Z3_context a0, Z3_ast a1, Z3_ast a2);
|
||||
#define LOG_Z3_mk_ge(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_ge(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_int2real(Z3_context a0, Z3_ast a1);
|
||||
#define LOG_Z3_mk_int2real(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_int2real(_ARG0, _ARG1); }
|
||||
void log_Z3_mk_real2int(Z3_context a0, Z3_ast a1);
|
||||
#define LOG_Z3_mk_real2int(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_real2int(_ARG0, _ARG1); }
|
||||
void log_Z3_mk_is_int(Z3_context a0, Z3_ast a1);
|
||||
#define LOG_Z3_mk_is_int(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_is_int(_ARG0, _ARG1); }
|
||||
void log_Z3_mk_bvnot(Z3_context a0, Z3_ast a1);
|
||||
#define LOG_Z3_mk_bvnot(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_bvnot(_ARG0, _ARG1); }
|
||||
void log_Z3_mk_bvredand(Z3_context a0, Z3_ast a1);
|
||||
#define LOG_Z3_mk_bvredand(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_bvredand(_ARG0, _ARG1); }
|
||||
void log_Z3_mk_bvredor(Z3_context a0, Z3_ast a1);
|
||||
#define LOG_Z3_mk_bvredor(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_bvredor(_ARG0, _ARG1); }
|
||||
void log_Z3_mk_bvand(Z3_context a0, Z3_ast a1, Z3_ast a2);
|
||||
#define LOG_Z3_mk_bvand(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_bvand(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_bvor(Z3_context a0, Z3_ast a1, Z3_ast a2);
|
||||
#define LOG_Z3_mk_bvor(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_bvor(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_bvxor(Z3_context a0, Z3_ast a1, Z3_ast a2);
|
||||
#define LOG_Z3_mk_bvxor(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_bvxor(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_bvnand(Z3_context a0, Z3_ast a1, Z3_ast a2);
|
||||
#define LOG_Z3_mk_bvnand(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_bvnand(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_bvnor(Z3_context a0, Z3_ast a1, Z3_ast a2);
|
||||
#define LOG_Z3_mk_bvnor(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_bvnor(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_bvxnor(Z3_context a0, Z3_ast a1, Z3_ast a2);
|
||||
#define LOG_Z3_mk_bvxnor(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_bvxnor(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_bvneg(Z3_context a0, Z3_ast a1);
|
||||
#define LOG_Z3_mk_bvneg(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_bvneg(_ARG0, _ARG1); }
|
||||
void log_Z3_mk_bvadd(Z3_context a0, Z3_ast a1, Z3_ast a2);
|
||||
#define LOG_Z3_mk_bvadd(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_bvadd(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_bvsub(Z3_context a0, Z3_ast a1, Z3_ast a2);
|
||||
#define LOG_Z3_mk_bvsub(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_bvsub(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_bvmul(Z3_context a0, Z3_ast a1, Z3_ast a2);
|
||||
#define LOG_Z3_mk_bvmul(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_bvmul(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_bvudiv(Z3_context a0, Z3_ast a1, Z3_ast a2);
|
||||
#define LOG_Z3_mk_bvudiv(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_bvudiv(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_bvsdiv(Z3_context a0, Z3_ast a1, Z3_ast a2);
|
||||
#define LOG_Z3_mk_bvsdiv(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_bvsdiv(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_bvurem(Z3_context a0, Z3_ast a1, Z3_ast a2);
|
||||
#define LOG_Z3_mk_bvurem(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_bvurem(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_bvsrem(Z3_context a0, Z3_ast a1, Z3_ast a2);
|
||||
#define LOG_Z3_mk_bvsrem(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_bvsrem(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_bvsmod(Z3_context a0, Z3_ast a1, Z3_ast a2);
|
||||
#define LOG_Z3_mk_bvsmod(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_bvsmod(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_bvult(Z3_context a0, Z3_ast a1, Z3_ast a2);
|
||||
#define LOG_Z3_mk_bvult(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_bvult(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_bvslt(Z3_context a0, Z3_ast a1, Z3_ast a2);
|
||||
#define LOG_Z3_mk_bvslt(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_bvslt(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_bvule(Z3_context a0, Z3_ast a1, Z3_ast a2);
|
||||
#define LOG_Z3_mk_bvule(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_bvule(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_bvsle(Z3_context a0, Z3_ast a1, Z3_ast a2);
|
||||
#define LOG_Z3_mk_bvsle(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_bvsle(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_bvuge(Z3_context a0, Z3_ast a1, Z3_ast a2);
|
||||
#define LOG_Z3_mk_bvuge(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_bvuge(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_bvsge(Z3_context a0, Z3_ast a1, Z3_ast a2);
|
||||
#define LOG_Z3_mk_bvsge(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_bvsge(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_bvugt(Z3_context a0, Z3_ast a1, Z3_ast a2);
|
||||
#define LOG_Z3_mk_bvugt(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_bvugt(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_bvsgt(Z3_context a0, Z3_ast a1, Z3_ast a2);
|
||||
#define LOG_Z3_mk_bvsgt(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_bvsgt(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_concat(Z3_context a0, Z3_ast a1, Z3_ast a2);
|
||||
#define LOG_Z3_mk_concat(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_concat(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_extract(Z3_context a0, unsigned a1, unsigned a2, Z3_ast a3);
|
||||
#define LOG_Z3_mk_extract(_ARG0, _ARG1, _ARG2, _ARG3) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_extract(_ARG0, _ARG1, _ARG2, _ARG3); }
|
||||
void log_Z3_mk_sign_ext(Z3_context a0, unsigned a1, Z3_ast a2);
|
||||
#define LOG_Z3_mk_sign_ext(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_sign_ext(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_zero_ext(Z3_context a0, unsigned a1, Z3_ast a2);
|
||||
#define LOG_Z3_mk_zero_ext(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_zero_ext(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_repeat(Z3_context a0, unsigned a1, Z3_ast a2);
|
||||
#define LOG_Z3_mk_repeat(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_repeat(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_bvshl(Z3_context a0, Z3_ast a1, Z3_ast a2);
|
||||
#define LOG_Z3_mk_bvshl(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_bvshl(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_bvlshr(Z3_context a0, Z3_ast a1, Z3_ast a2);
|
||||
#define LOG_Z3_mk_bvlshr(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_bvlshr(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_bvashr(Z3_context a0, Z3_ast a1, Z3_ast a2);
|
||||
#define LOG_Z3_mk_bvashr(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_bvashr(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_rotate_left(Z3_context a0, unsigned a1, Z3_ast a2);
|
||||
#define LOG_Z3_mk_rotate_left(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_rotate_left(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_rotate_right(Z3_context a0, unsigned a1, Z3_ast a2);
|
||||
#define LOG_Z3_mk_rotate_right(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_rotate_right(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_ext_rotate_left(Z3_context a0, Z3_ast a1, Z3_ast a2);
|
||||
#define LOG_Z3_mk_ext_rotate_left(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_ext_rotate_left(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_ext_rotate_right(Z3_context a0, Z3_ast a1, Z3_ast a2);
|
||||
#define LOG_Z3_mk_ext_rotate_right(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_ext_rotate_right(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_int2bv(Z3_context a0, unsigned a1, Z3_ast a2);
|
||||
#define LOG_Z3_mk_int2bv(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_int2bv(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_bv2int(Z3_context a0, Z3_ast a1, Z3_bool a2);
|
||||
#define LOG_Z3_mk_bv2int(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_bv2int(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_bvadd_no_overflow(Z3_context a0, Z3_ast a1, Z3_ast a2, Z3_bool a3);
|
||||
#define LOG_Z3_mk_bvadd_no_overflow(_ARG0, _ARG1, _ARG2, _ARG3) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_bvadd_no_overflow(_ARG0, _ARG1, _ARG2, _ARG3); }
|
||||
void log_Z3_mk_bvadd_no_underflow(Z3_context a0, Z3_ast a1, Z3_ast a2);
|
||||
#define LOG_Z3_mk_bvadd_no_underflow(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_bvadd_no_underflow(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_bvsub_no_overflow(Z3_context a0, Z3_ast a1, Z3_ast a2);
|
||||
#define LOG_Z3_mk_bvsub_no_overflow(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_bvsub_no_overflow(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_bvsub_no_underflow(Z3_context a0, Z3_ast a1, Z3_ast a2, Z3_bool a3);
|
||||
#define LOG_Z3_mk_bvsub_no_underflow(_ARG0, _ARG1, _ARG2, _ARG3) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_bvsub_no_underflow(_ARG0, _ARG1, _ARG2, _ARG3); }
|
||||
void log_Z3_mk_bvsdiv_no_overflow(Z3_context a0, Z3_ast a1, Z3_ast a2);
|
||||
#define LOG_Z3_mk_bvsdiv_no_overflow(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_bvsdiv_no_overflow(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_bvneg_no_overflow(Z3_context a0, Z3_ast a1);
|
||||
#define LOG_Z3_mk_bvneg_no_overflow(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_bvneg_no_overflow(_ARG0, _ARG1); }
|
||||
void log_Z3_mk_bvmul_no_overflow(Z3_context a0, Z3_ast a1, Z3_ast a2, Z3_bool a3);
|
||||
#define LOG_Z3_mk_bvmul_no_overflow(_ARG0, _ARG1, _ARG2, _ARG3) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_bvmul_no_overflow(_ARG0, _ARG1, _ARG2, _ARG3); }
|
||||
void log_Z3_mk_bvmul_no_underflow(Z3_context a0, Z3_ast a1, Z3_ast a2);
|
||||
#define LOG_Z3_mk_bvmul_no_underflow(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_bvmul_no_underflow(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_select(Z3_context a0, Z3_ast a1, Z3_ast a2);
|
||||
#define LOG_Z3_mk_select(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_select(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_store(Z3_context a0, Z3_ast a1, Z3_ast a2, Z3_ast a3);
|
||||
#define LOG_Z3_mk_store(_ARG0, _ARG1, _ARG2, _ARG3) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_store(_ARG0, _ARG1, _ARG2, _ARG3); }
|
||||
void log_Z3_mk_const_array(Z3_context a0, Z3_sort a1, Z3_ast a2);
|
||||
#define LOG_Z3_mk_const_array(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_const_array(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_map(Z3_context a0, Z3_func_decl a1, unsigned a2, Z3_ast const * a3);
|
||||
#define LOG_Z3_mk_map(_ARG0, _ARG1, _ARG2, _ARG3) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_map(_ARG0, _ARG1, _ARG2, _ARG3); }
|
||||
void log_Z3_mk_array_default(Z3_context a0, Z3_ast a1);
|
||||
#define LOG_Z3_mk_array_default(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_array_default(_ARG0, _ARG1); }
|
||||
void log_Z3_mk_set_sort(Z3_context a0, Z3_sort a1);
|
||||
#define LOG_Z3_mk_set_sort(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_set_sort(_ARG0, _ARG1); }
|
||||
void log_Z3_mk_empty_set(Z3_context a0, Z3_sort a1);
|
||||
#define LOG_Z3_mk_empty_set(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_empty_set(_ARG0, _ARG1); }
|
||||
void log_Z3_mk_full_set(Z3_context a0, Z3_sort a1);
|
||||
#define LOG_Z3_mk_full_set(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_full_set(_ARG0, _ARG1); }
|
||||
void log_Z3_mk_set_add(Z3_context a0, Z3_ast a1, Z3_ast a2);
|
||||
#define LOG_Z3_mk_set_add(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_set_add(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_set_del(Z3_context a0, Z3_ast a1, Z3_ast a2);
|
||||
#define LOG_Z3_mk_set_del(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_set_del(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_set_union(Z3_context a0, unsigned a1, Z3_ast const * a2);
|
||||
#define LOG_Z3_mk_set_union(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_set_union(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_set_intersect(Z3_context a0, unsigned a1, Z3_ast const * a2);
|
||||
#define LOG_Z3_mk_set_intersect(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_set_intersect(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_set_difference(Z3_context a0, Z3_ast a1, Z3_ast a2);
|
||||
#define LOG_Z3_mk_set_difference(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_set_difference(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_set_complement(Z3_context a0, Z3_ast a1);
|
||||
#define LOG_Z3_mk_set_complement(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_set_complement(_ARG0, _ARG1); }
|
||||
void log_Z3_mk_set_member(Z3_context a0, Z3_ast a1, Z3_ast a2);
|
||||
#define LOG_Z3_mk_set_member(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_set_member(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_set_subset(Z3_context a0, Z3_ast a1, Z3_ast a2);
|
||||
#define LOG_Z3_mk_set_subset(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_set_subset(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_numeral(Z3_context a0, Z3_string a1, Z3_sort a2);
|
||||
#define LOG_Z3_mk_numeral(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_numeral(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_real(Z3_context a0, int a1, int a2);
|
||||
#define LOG_Z3_mk_real(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_real(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_int(Z3_context a0, int a1, Z3_sort a2);
|
||||
#define LOG_Z3_mk_int(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_int(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_unsigned_int(Z3_context a0, unsigned a1, Z3_sort a2);
|
||||
#define LOG_Z3_mk_unsigned_int(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_unsigned_int(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_int64(Z3_context a0, __int64 a1, Z3_sort a2);
|
||||
#define LOG_Z3_mk_int64(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_int64(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_unsigned_int64(Z3_context a0, __uint64 a1, Z3_sort a2);
|
||||
#define LOG_Z3_mk_unsigned_int64(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_unsigned_int64(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_pattern(Z3_context a0, unsigned a1, Z3_ast const * a2);
|
||||
#define LOG_Z3_mk_pattern(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_pattern(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_bound(Z3_context a0, unsigned a1, Z3_sort a2);
|
||||
#define LOG_Z3_mk_bound(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_bound(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_forall(Z3_context a0, unsigned a1, unsigned a2, Z3_pattern const * a3, unsigned a4, Z3_sort const * a5, Z3_symbol const * a6, Z3_ast a7);
|
||||
#define LOG_Z3_mk_forall(_ARG0, _ARG1, _ARG2, _ARG3, _ARG4, _ARG5, _ARG6, _ARG7) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_forall(_ARG0, _ARG1, _ARG2, _ARG3, _ARG4, _ARG5, _ARG6, _ARG7); }
|
||||
void log_Z3_mk_exists(Z3_context a0, unsigned a1, unsigned a2, Z3_pattern const * a3, unsigned a4, Z3_sort const * a5, Z3_symbol const * a6, Z3_ast a7);
|
||||
#define LOG_Z3_mk_exists(_ARG0, _ARG1, _ARG2, _ARG3, _ARG4, _ARG5, _ARG6, _ARG7) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_exists(_ARG0, _ARG1, _ARG2, _ARG3, _ARG4, _ARG5, _ARG6, _ARG7); }
|
||||
void log_Z3_mk_quantifier(Z3_context a0, Z3_bool a1, unsigned a2, unsigned a3, Z3_pattern const * a4, unsigned a5, Z3_sort const * a6, Z3_symbol const * a7, Z3_ast a8);
|
||||
#define LOG_Z3_mk_quantifier(_ARG0, _ARG1, _ARG2, _ARG3, _ARG4, _ARG5, _ARG6, _ARG7, _ARG8) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_quantifier(_ARG0, _ARG1, _ARG2, _ARG3, _ARG4, _ARG5, _ARG6, _ARG7, _ARG8); }
|
||||
void log_Z3_mk_quantifier_ex(Z3_context a0, Z3_bool a1, unsigned a2, Z3_symbol a3, Z3_symbol a4, unsigned a5, Z3_pattern const * a6, unsigned a7, Z3_ast const * a8, unsigned a9, Z3_sort const * a10, Z3_symbol const * a11, Z3_ast a12);
|
||||
#define LOG_Z3_mk_quantifier_ex(_ARG0, _ARG1, _ARG2, _ARG3, _ARG4, _ARG5, _ARG6, _ARG7, _ARG8, _ARG9, _ARG10, _ARG11, _ARG12) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_quantifier_ex(_ARG0, _ARG1, _ARG2, _ARG3, _ARG4, _ARG5, _ARG6, _ARG7, _ARG8, _ARG9, _ARG10, _ARG11, _ARG12); }
|
||||
void log_Z3_mk_forall_const(Z3_context a0, unsigned a1, unsigned a2, Z3_app const * a3, unsigned a4, Z3_pattern const * a5, Z3_ast a6);
|
||||
#define LOG_Z3_mk_forall_const(_ARG0, _ARG1, _ARG2, _ARG3, _ARG4, _ARG5, _ARG6) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_forall_const(_ARG0, _ARG1, _ARG2, _ARG3, _ARG4, _ARG5, _ARG6); }
|
||||
void log_Z3_mk_exists_const(Z3_context a0, unsigned a1, unsigned a2, Z3_app const * a3, unsigned a4, Z3_pattern const * a5, Z3_ast a6);
|
||||
#define LOG_Z3_mk_exists_const(_ARG0, _ARG1, _ARG2, _ARG3, _ARG4, _ARG5, _ARG6) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_exists_const(_ARG0, _ARG1, _ARG2, _ARG3, _ARG4, _ARG5, _ARG6); }
|
||||
void log_Z3_mk_quantifier_const(Z3_context a0, Z3_bool a1, unsigned a2, unsigned a3, Z3_app const * a4, unsigned a5, Z3_pattern const * a6, Z3_ast a7);
|
||||
#define LOG_Z3_mk_quantifier_const(_ARG0, _ARG1, _ARG2, _ARG3, _ARG4, _ARG5, _ARG6, _ARG7) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_quantifier_const(_ARG0, _ARG1, _ARG2, _ARG3, _ARG4, _ARG5, _ARG6, _ARG7); }
|
||||
void log_Z3_mk_quantifier_const_ex(Z3_context a0, Z3_bool a1, unsigned a2, Z3_symbol a3, Z3_symbol a4, unsigned a5, Z3_app const * a6, unsigned a7, Z3_pattern const * a8, unsigned a9, Z3_ast const * a10, Z3_ast a11);
|
||||
#define LOG_Z3_mk_quantifier_const_ex(_ARG0, _ARG1, _ARG2, _ARG3, _ARG4, _ARG5, _ARG6, _ARG7, _ARG8, _ARG9, _ARG10, _ARG11) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_quantifier_const_ex(_ARG0, _ARG1, _ARG2, _ARG3, _ARG4, _ARG5, _ARG6, _ARG7, _ARG8, _ARG9, _ARG10, _ARG11); }
|
||||
void log_Z3_get_ast_id(Z3_context a0, Z3_ast a1);
|
||||
#define LOG_Z3_get_ast_id(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_ast_id(_ARG0, _ARG1); }
|
||||
void log_Z3_get_func_decl_id(Z3_context a0, Z3_func_decl a1);
|
||||
#define LOG_Z3_get_func_decl_id(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_func_decl_id(_ARG0, _ARG1); }
|
||||
void log_Z3_get_sort_id(Z3_context a0, Z3_sort a1);
|
||||
#define LOG_Z3_get_sort_id(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_sort_id(_ARG0, _ARG1); }
|
||||
void log_Z3_is_well_sorted(Z3_context a0, Z3_ast a1);
|
||||
#define LOG_Z3_is_well_sorted(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_is_well_sorted(_ARG0, _ARG1); }
|
||||
void log_Z3_get_symbol_kind(Z3_context a0, Z3_symbol a1);
|
||||
#define LOG_Z3_get_symbol_kind(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_symbol_kind(_ARG0, _ARG1); }
|
||||
void log_Z3_get_symbol_int(Z3_context a0, Z3_symbol a1);
|
||||
#define LOG_Z3_get_symbol_int(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_symbol_int(_ARG0, _ARG1); }
|
||||
void log_Z3_get_symbol_string(Z3_context a0, Z3_symbol a1);
|
||||
#define LOG_Z3_get_symbol_string(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_symbol_string(_ARG0, _ARG1); }
|
||||
void log_Z3_get_ast_kind(Z3_context a0, Z3_ast a1);
|
||||
#define LOG_Z3_get_ast_kind(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_ast_kind(_ARG0, _ARG1); }
|
||||
void log_Z3_get_ast_hash(Z3_context a0, Z3_ast a1);
|
||||
#define LOG_Z3_get_ast_hash(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_ast_hash(_ARG0, _ARG1); }
|
||||
void log_Z3_get_numeral_string(Z3_context a0, Z3_ast a1);
|
||||
#define LOG_Z3_get_numeral_string(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_numeral_string(_ARG0, _ARG1); }
|
||||
void log_Z3_get_numeral_decimal_string(Z3_context a0, Z3_ast a1, unsigned a2);
|
||||
#define LOG_Z3_get_numeral_decimal_string(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_numeral_decimal_string(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_get_numerator(Z3_context a0, Z3_ast a1);
|
||||
#define LOG_Z3_get_numerator(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_numerator(_ARG0, _ARG1); }
|
||||
void log_Z3_get_denominator(Z3_context a0, Z3_ast a1);
|
||||
#define LOG_Z3_get_denominator(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_denominator(_ARG0, _ARG1); }
|
||||
void log_Z3_get_numeral_small(Z3_context a0, Z3_ast a1, __int64* a2, __int64* a3);
|
||||
#define LOG_Z3_get_numeral_small(_ARG0, _ARG1, _ARG2, _ARG3) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_numeral_small(_ARG0, _ARG1, _ARG2, _ARG3); }
|
||||
void log_Z3_get_numeral_int(Z3_context a0, Z3_ast a1, int* a2);
|
||||
#define LOG_Z3_get_numeral_int(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_numeral_int(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_get_numeral_uint(Z3_context a0, Z3_ast a1, unsigned* a2);
|
||||
#define LOG_Z3_get_numeral_uint(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_numeral_uint(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_get_numeral_uint64(Z3_context a0, Z3_ast a1, __uint64* a2);
|
||||
#define LOG_Z3_get_numeral_uint64(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_numeral_uint64(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_get_numeral_int64(Z3_context a0, Z3_ast a1, __int64* a2);
|
||||
#define LOG_Z3_get_numeral_int64(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_numeral_int64(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_get_numeral_rational_int64(Z3_context a0, Z3_ast a1, __int64* a2, __int64* a3);
|
||||
#define LOG_Z3_get_numeral_rational_int64(_ARG0, _ARG1, _ARG2, _ARG3) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_numeral_rational_int64(_ARG0, _ARG1, _ARG2, _ARG3); }
|
||||
void log_Z3_get_bool_value(Z3_context a0, Z3_ast a1);
|
||||
#define LOG_Z3_get_bool_value(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_bool_value(_ARG0, _ARG1); }
|
||||
void log_Z3_get_app_decl(Z3_context a0, Z3_app a1);
|
||||
#define LOG_Z3_get_app_decl(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_app_decl(_ARG0, _ARG1); }
|
||||
void log_Z3_get_app_num_args(Z3_context a0, Z3_app a1);
|
||||
#define LOG_Z3_get_app_num_args(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_app_num_args(_ARG0, _ARG1); }
|
||||
void log_Z3_get_app_arg(Z3_context a0, Z3_app a1, unsigned a2);
|
||||
#define LOG_Z3_get_app_arg(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_app_arg(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_get_index_value(Z3_context a0, Z3_ast a1);
|
||||
#define LOG_Z3_get_index_value(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_index_value(_ARG0, _ARG1); }
|
||||
void log_Z3_is_quantifier_forall(Z3_context a0, Z3_ast a1);
|
||||
#define LOG_Z3_is_quantifier_forall(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_is_quantifier_forall(_ARG0, _ARG1); }
|
||||
void log_Z3_get_quantifier_weight(Z3_context a0, Z3_ast a1);
|
||||
#define LOG_Z3_get_quantifier_weight(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_quantifier_weight(_ARG0, _ARG1); }
|
||||
void log_Z3_get_quantifier_num_patterns(Z3_context a0, Z3_ast a1);
|
||||
#define LOG_Z3_get_quantifier_num_patterns(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_quantifier_num_patterns(_ARG0, _ARG1); }
|
||||
void log_Z3_get_quantifier_pattern_ast(Z3_context a0, Z3_ast a1, unsigned a2);
|
||||
#define LOG_Z3_get_quantifier_pattern_ast(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_quantifier_pattern_ast(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_get_quantifier_num_no_patterns(Z3_context a0, Z3_ast a1);
|
||||
#define LOG_Z3_get_quantifier_num_no_patterns(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_quantifier_num_no_patterns(_ARG0, _ARG1); }
|
||||
void log_Z3_get_quantifier_no_pattern_ast(Z3_context a0, Z3_ast a1, unsigned a2);
|
||||
#define LOG_Z3_get_quantifier_no_pattern_ast(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_quantifier_no_pattern_ast(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_get_quantifier_bound_name(Z3_context a0, Z3_ast a1, unsigned a2);
|
||||
#define LOG_Z3_get_quantifier_bound_name(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_quantifier_bound_name(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_get_quantifier_bound_sort(Z3_context a0, Z3_ast a1, unsigned a2);
|
||||
#define LOG_Z3_get_quantifier_bound_sort(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_quantifier_bound_sort(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_get_quantifier_body(Z3_context a0, Z3_ast a1);
|
||||
#define LOG_Z3_get_quantifier_body(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_quantifier_body(_ARG0, _ARG1); }
|
||||
void log_Z3_get_quantifier_num_bound(Z3_context a0, Z3_ast a1);
|
||||
#define LOG_Z3_get_quantifier_num_bound(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_quantifier_num_bound(_ARG0, _ARG1); }
|
||||
void log_Z3_get_decl_name(Z3_context a0, Z3_func_decl a1);
|
||||
#define LOG_Z3_get_decl_name(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_decl_name(_ARG0, _ARG1); }
|
||||
void log_Z3_get_decl_num_parameters(Z3_context a0, Z3_func_decl a1);
|
||||
#define LOG_Z3_get_decl_num_parameters(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_decl_num_parameters(_ARG0, _ARG1); }
|
||||
void log_Z3_get_decl_parameter_kind(Z3_context a0, Z3_func_decl a1, unsigned a2);
|
||||
#define LOG_Z3_get_decl_parameter_kind(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_decl_parameter_kind(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_get_decl_int_parameter(Z3_context a0, Z3_func_decl a1, unsigned a2);
|
||||
#define LOG_Z3_get_decl_int_parameter(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_decl_int_parameter(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_get_decl_double_parameter(Z3_context a0, Z3_func_decl a1, unsigned a2);
|
||||
#define LOG_Z3_get_decl_double_parameter(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_decl_double_parameter(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_get_decl_symbol_parameter(Z3_context a0, Z3_func_decl a1, unsigned a2);
|
||||
#define LOG_Z3_get_decl_symbol_parameter(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_decl_symbol_parameter(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_get_decl_sort_parameter(Z3_context a0, Z3_func_decl a1, unsigned a2);
|
||||
#define LOG_Z3_get_decl_sort_parameter(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_decl_sort_parameter(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_get_decl_ast_parameter(Z3_context a0, Z3_func_decl a1, unsigned a2);
|
||||
#define LOG_Z3_get_decl_ast_parameter(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_decl_ast_parameter(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_get_decl_func_decl_parameter(Z3_context a0, Z3_func_decl a1, unsigned a2);
|
||||
#define LOG_Z3_get_decl_func_decl_parameter(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_decl_func_decl_parameter(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_get_decl_rational_parameter(Z3_context a0, Z3_func_decl a1, unsigned a2);
|
||||
#define LOG_Z3_get_decl_rational_parameter(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_decl_rational_parameter(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_get_sort_name(Z3_context a0, Z3_sort a1);
|
||||
#define LOG_Z3_get_sort_name(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_sort_name(_ARG0, _ARG1); }
|
||||
void log_Z3_get_sort(Z3_context a0, Z3_ast a1);
|
||||
#define LOG_Z3_get_sort(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_sort(_ARG0, _ARG1); }
|
||||
void log_Z3_get_domain_size(Z3_context a0, Z3_func_decl a1);
|
||||
#define LOG_Z3_get_domain_size(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_domain_size(_ARG0, _ARG1); }
|
||||
void log_Z3_get_domain(Z3_context a0, Z3_func_decl a1, unsigned a2);
|
||||
#define LOG_Z3_get_domain(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_domain(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_get_range(Z3_context a0, Z3_func_decl a1);
|
||||
#define LOG_Z3_get_range(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_range(_ARG0, _ARG1); }
|
||||
void log_Z3_get_sort_kind(Z3_context a0, Z3_sort a1);
|
||||
#define LOG_Z3_get_sort_kind(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_sort_kind(_ARG0, _ARG1); }
|
||||
void log_Z3_get_bv_sort_size(Z3_context a0, Z3_sort a1);
|
||||
#define LOG_Z3_get_bv_sort_size(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_bv_sort_size(_ARG0, _ARG1); }
|
||||
void log_Z3_get_array_sort_domain(Z3_context a0, Z3_sort a1);
|
||||
#define LOG_Z3_get_array_sort_domain(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_array_sort_domain(_ARG0, _ARG1); }
|
||||
void log_Z3_get_array_sort_range(Z3_context a0, Z3_sort a1);
|
||||
#define LOG_Z3_get_array_sort_range(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_array_sort_range(_ARG0, _ARG1); }
|
||||
void log_Z3_get_tuple_sort_mk_decl(Z3_context a0, Z3_sort a1);
|
||||
#define LOG_Z3_get_tuple_sort_mk_decl(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_tuple_sort_mk_decl(_ARG0, _ARG1); }
|
||||
void log_Z3_get_decl_kind(Z3_context a0, Z3_func_decl a1);
|
||||
#define LOG_Z3_get_decl_kind(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_decl_kind(_ARG0, _ARG1); }
|
||||
void log_Z3_get_tuple_sort_num_fields(Z3_context a0, Z3_sort a1);
|
||||
#define LOG_Z3_get_tuple_sort_num_fields(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_tuple_sort_num_fields(_ARG0, _ARG1); }
|
||||
void log_Z3_get_tuple_sort_field_decl(Z3_context a0, Z3_sort a1, unsigned a2);
|
||||
#define LOG_Z3_get_tuple_sort_field_decl(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_tuple_sort_field_decl(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_get_datatype_sort_num_constructors(Z3_context a0, Z3_sort a1);
|
||||
#define LOG_Z3_get_datatype_sort_num_constructors(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_datatype_sort_num_constructors(_ARG0, _ARG1); }
|
||||
void log_Z3_get_datatype_sort_constructor(Z3_context a0, Z3_sort a1, unsigned a2);
|
||||
#define LOG_Z3_get_datatype_sort_constructor(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_datatype_sort_constructor(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_get_datatype_sort_recognizer(Z3_context a0, Z3_sort a1, unsigned a2);
|
||||
#define LOG_Z3_get_datatype_sort_recognizer(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_datatype_sort_recognizer(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_get_datatype_sort_constructor_accessor(Z3_context a0, Z3_sort a1, unsigned a2, unsigned a3);
|
||||
#define LOG_Z3_get_datatype_sort_constructor_accessor(_ARG0, _ARG1, _ARG2, _ARG3) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_datatype_sort_constructor_accessor(_ARG0, _ARG1, _ARG2, _ARG3); }
|
||||
void log_Z3_get_relation_arity(Z3_context a0, Z3_sort a1);
|
||||
#define LOG_Z3_get_relation_arity(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_relation_arity(_ARG0, _ARG1); }
|
||||
void log_Z3_get_relation_column(Z3_context a0, Z3_sort a1, unsigned a2);
|
||||
#define LOG_Z3_get_relation_column(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_relation_column(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_get_finite_domain_sort_size(Z3_context a0, Z3_sort a1, __uint64* a2);
|
||||
#define LOG_Z3_get_finite_domain_sort_size(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_finite_domain_sort_size(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_finite_domain_sort(Z3_context a0, Z3_symbol a1, __uint64 a2);
|
||||
#define LOG_Z3_mk_finite_domain_sort(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_finite_domain_sort(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_get_pattern_num_terms(Z3_context a0, Z3_pattern a1);
|
||||
#define LOG_Z3_get_pattern_num_terms(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_pattern_num_terms(_ARG0, _ARG1); }
|
||||
void log_Z3_get_pattern(Z3_context a0, Z3_pattern a1, unsigned a2);
|
||||
#define LOG_Z3_get_pattern(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_pattern(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_simplify(Z3_context a0, Z3_ast a1);
|
||||
#define LOG_Z3_simplify(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_simplify(_ARG0, _ARG1); }
|
||||
void log_Z3_simplify_ex(Z3_context a0, Z3_ast a1, Z3_params a2);
|
||||
#define LOG_Z3_simplify_ex(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_simplify_ex(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_simplify_get_help(Z3_context a0);
|
||||
#define LOG_Z3_simplify_get_help(_ARG0) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_simplify_get_help(_ARG0); }
|
||||
void log_Z3_simplify_get_param_descrs(Z3_context a0);
|
||||
#define LOG_Z3_simplify_get_param_descrs(_ARG0) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_simplify_get_param_descrs(_ARG0); }
|
||||
void log_Z3_update_term(Z3_context a0, Z3_ast a1, unsigned a2, Z3_ast const * a3);
|
||||
#define LOG_Z3_update_term(_ARG0, _ARG1, _ARG2, _ARG3) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_update_term(_ARG0, _ARG1, _ARG2, _ARG3); }
|
||||
void log_Z3_substitute(Z3_context a0, Z3_ast a1, unsigned a2, Z3_ast const * a3, Z3_ast const * a4);
|
||||
#define LOG_Z3_substitute(_ARG0, _ARG1, _ARG2, _ARG3, _ARG4) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_substitute(_ARG0, _ARG1, _ARG2, _ARG3, _ARG4); }
|
||||
void log_Z3_substitute_vars(Z3_context a0, Z3_ast a1, unsigned a2, Z3_ast const * a3);
|
||||
#define LOG_Z3_substitute_vars(_ARG0, _ARG1, _ARG2, _ARG3) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_substitute_vars(_ARG0, _ARG1, _ARG2, _ARG3); }
|
||||
void log_Z3_sort_to_ast(Z3_context a0, Z3_sort a1);
|
||||
#define LOG_Z3_sort_to_ast(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_sort_to_ast(_ARG0, _ARG1); }
|
||||
void log_Z3_func_decl_to_ast(Z3_context a0, Z3_func_decl a1);
|
||||
#define LOG_Z3_func_decl_to_ast(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_func_decl_to_ast(_ARG0, _ARG1); }
|
||||
void log_Z3_pattern_to_ast(Z3_context a0, Z3_pattern a1);
|
||||
#define LOG_Z3_pattern_to_ast(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_pattern_to_ast(_ARG0, _ARG1); }
|
||||
void log_Z3_app_to_ast(Z3_context a0, Z3_app a1);
|
||||
#define LOG_Z3_app_to_ast(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_app_to_ast(_ARG0, _ARG1); }
|
||||
void log_Z3_to_app(Z3_context a0, Z3_ast a1);
|
||||
#define LOG_Z3_to_app(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_to_app(_ARG0, _ARG1); }
|
||||
void log_Z3_to_func_decl(Z3_context a0, Z3_ast a1);
|
||||
#define LOG_Z3_to_func_decl(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_to_func_decl(_ARG0, _ARG1); }
|
||||
void log_Z3_push(Z3_context a0);
|
||||
#define LOG_Z3_push(_ARG0) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_push(_ARG0); }
|
||||
void log_Z3_pop(Z3_context a0, unsigned a1);
|
||||
#define LOG_Z3_pop(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_pop(_ARG0, _ARG1); }
|
||||
void log_Z3_get_num_scopes(Z3_context a0);
|
||||
#define LOG_Z3_get_num_scopes(_ARG0) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_num_scopes(_ARG0); }
|
||||
void log_Z3_persist_ast(Z3_context a0, Z3_ast a1, unsigned a2);
|
||||
#define LOG_Z3_persist_ast(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_persist_ast(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_assert_cnstr(Z3_context a0, Z3_ast a1);
|
||||
#define LOG_Z3_assert_cnstr(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_assert_cnstr(_ARG0, _ARG1); }
|
||||
void log_Z3_check_and_get_model(Z3_context a0, Z3_model* a1);
|
||||
#define LOG_Z3_check_and_get_model(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; Z3_model* Z3ARG1; if (_LOG_CTX.enabled()) { log_Z3_check_and_get_model(_ARG0, _ARG1); Z3ARG1 = _ARG1; }
|
||||
#define RETURN_Z3_check_and_get_model if (_LOG_CTX.enabled()) { SetO((Z3ARG1 == 0 ? 0 : *Z3ARG1), 1); } return
|
||||
void log_Z3_check(Z3_context a0);
|
||||
#define LOG_Z3_check(_ARG0) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_check(_ARG0); }
|
||||
void log_Z3_check_assumptions(Z3_context a0, unsigned a1, Z3_ast const * a2, Z3_model* a3, Z3_ast* a4, unsigned* a5, Z3_ast* a6);
|
||||
#define LOG_Z3_check_assumptions(_ARG0, _ARG1, _ARG2, _ARG3, _ARG4, _ARG5, _ARG6) z3_log_ctx _LOG_CTX; Z3_model* Z3ARG3; Z3_ast* Z3ARG4; unsigned Z3ARG1; unsigned * Z3ARG5; Z3_ast* Z3ARG6; if (_LOG_CTX.enabled()) { log_Z3_check_assumptions(_ARG0, _ARG1, _ARG2, _ARG3, _ARG4, _ARG5, _ARG6); Z3ARG3 = _ARG3; Z3ARG4 = _ARG4; Z3ARG1 = _ARG1; Z3ARG5 = _ARG5; Z3ARG6 = _ARG6; }
|
||||
#define RETURN_Z3_check_assumptions if (_LOG_CTX.enabled()) { SetO((Z3ARG3 == 0 ? 0 : *Z3ARG3), 3); SetO((Z3ARG4 == 0 ? 0 : *Z3ARG4), 4); for (unsigned i = 0; Z3ARG5 && i < *Z3ARG5; i++) { SetAO(Z3ARG6[i], 6, i); } } return
|
||||
void log_Z3_get_implied_equalities(Z3_context a0, unsigned a1, Z3_ast const * a2, unsigned* a3);
|
||||
#define LOG_Z3_get_implied_equalities(_ARG0, _ARG1, _ARG2, _ARG3) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_implied_equalities(_ARG0, _ARG1, _ARG2, _ARG3); }
|
||||
void log_Z3_del_model(Z3_context a0, Z3_model a1);
|
||||
#define LOG_Z3_del_model(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_del_model(_ARG0, _ARG1); }
|
||||
void log_Z3_soft_check_cancel(Z3_context a0);
|
||||
#define LOG_Z3_soft_check_cancel(_ARG0) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_soft_check_cancel(_ARG0); }
|
||||
void log_Z3_get_search_failure(Z3_context a0);
|
||||
#define LOG_Z3_get_search_failure(_ARG0) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_search_failure(_ARG0); }
|
||||
void log_Z3_get_relevant_labels(Z3_context a0);
|
||||
#define LOG_Z3_get_relevant_labels(_ARG0) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_relevant_labels(_ARG0); }
|
||||
void log_Z3_get_relevant_literals(Z3_context a0);
|
||||
#define LOG_Z3_get_relevant_literals(_ARG0) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_relevant_literals(_ARG0); }
|
||||
void log_Z3_get_guessed_literals(Z3_context a0);
|
||||
#define LOG_Z3_get_guessed_literals(_ARG0) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_guessed_literals(_ARG0); }
|
||||
void log_Z3_del_literals(Z3_context a0, Z3_literals a1);
|
||||
#define LOG_Z3_del_literals(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_del_literals(_ARG0, _ARG1); }
|
||||
void log_Z3_get_num_literals(Z3_context a0, Z3_literals a1);
|
||||
#define LOG_Z3_get_num_literals(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_num_literals(_ARG0, _ARG1); }
|
||||
void log_Z3_get_label_symbol(Z3_context a0, Z3_literals a1, unsigned a2);
|
||||
#define LOG_Z3_get_label_symbol(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_label_symbol(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_get_literal(Z3_context a0, Z3_literals a1, unsigned a2);
|
||||
#define LOG_Z3_get_literal(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_literal(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_disable_literal(Z3_context a0, Z3_literals a1, unsigned a2);
|
||||
#define LOG_Z3_disable_literal(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_disable_literal(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_block_literals(Z3_context a0, Z3_literals a1);
|
||||
#define LOG_Z3_block_literals(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_block_literals(_ARG0, _ARG1); }
|
||||
void log_Z3_model_inc_ref(Z3_context a0, Z3_model a1);
|
||||
#define LOG_Z3_model_inc_ref(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_model_inc_ref(_ARG0, _ARG1); }
|
||||
void log_Z3_model_dec_ref(Z3_context a0, Z3_model a1);
|
||||
#define LOG_Z3_model_dec_ref(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_model_dec_ref(_ARG0, _ARG1); }
|
||||
void log_Z3_model_get_const_interp(Z3_context a0, Z3_model a1, Z3_func_decl a2);
|
||||
#define LOG_Z3_model_get_const_interp(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_model_get_const_interp(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_model_get_func_interp(Z3_context a0, Z3_model a1, Z3_func_decl a2);
|
||||
#define LOG_Z3_model_get_func_interp(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_model_get_func_interp(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_model_get_num_consts(Z3_context a0, Z3_model a1);
|
||||
#define LOG_Z3_model_get_num_consts(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_model_get_num_consts(_ARG0, _ARG1); }
|
||||
void log_Z3_model_get_const_decl(Z3_context a0, Z3_model a1, unsigned a2);
|
||||
#define LOG_Z3_model_get_const_decl(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_model_get_const_decl(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_model_get_num_funcs(Z3_context a0, Z3_model a1);
|
||||
#define LOG_Z3_model_get_num_funcs(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_model_get_num_funcs(_ARG0, _ARG1); }
|
||||
void log_Z3_model_get_func_decl(Z3_context a0, Z3_model a1, unsigned a2);
|
||||
#define LOG_Z3_model_get_func_decl(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_model_get_func_decl(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_model_eval(Z3_context a0, Z3_model a1, Z3_ast a2, Z3_bool a3, Z3_ast* a4);
|
||||
#define LOG_Z3_model_eval(_ARG0, _ARG1, _ARG2, _ARG3, _ARG4) z3_log_ctx _LOG_CTX; Z3_ast* Z3ARG4; if (_LOG_CTX.enabled()) { log_Z3_model_eval(_ARG0, _ARG1, _ARG2, _ARG3, _ARG4); Z3ARG4 = _ARG4; }
|
||||
#define RETURN_Z3_model_eval if (_LOG_CTX.enabled()) { SetO((Z3ARG4 == 0 ? 0 : *Z3ARG4), 4); } return
|
||||
void log_Z3_model_get_num_sorts(Z3_context a0, Z3_model a1);
|
||||
#define LOG_Z3_model_get_num_sorts(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_model_get_num_sorts(_ARG0, _ARG1); }
|
||||
void log_Z3_model_get_sort(Z3_context a0, Z3_model a1, unsigned a2);
|
||||
#define LOG_Z3_model_get_sort(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_model_get_sort(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_model_get_sort_universe(Z3_context a0, Z3_model a1, Z3_sort a2);
|
||||
#define LOG_Z3_model_get_sort_universe(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_model_get_sort_universe(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_is_as_array(Z3_context a0, Z3_ast a1);
|
||||
#define LOG_Z3_is_as_array(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_is_as_array(_ARG0, _ARG1); }
|
||||
void log_Z3_get_as_array_func_decl(Z3_context a0, Z3_ast a1);
|
||||
#define LOG_Z3_get_as_array_func_decl(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_as_array_func_decl(_ARG0, _ARG1); }
|
||||
void log_Z3_func_interp_inc_ref(Z3_context a0, Z3_func_interp a1);
|
||||
#define LOG_Z3_func_interp_inc_ref(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_func_interp_inc_ref(_ARG0, _ARG1); }
|
||||
void log_Z3_func_interp_dec_ref(Z3_context a0, Z3_func_interp a1);
|
||||
#define LOG_Z3_func_interp_dec_ref(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_func_interp_dec_ref(_ARG0, _ARG1); }
|
||||
void log_Z3_func_interp_get_num_entries(Z3_context a0, Z3_func_interp a1);
|
||||
#define LOG_Z3_func_interp_get_num_entries(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_func_interp_get_num_entries(_ARG0, _ARG1); }
|
||||
void log_Z3_func_interp_get_entry(Z3_context a0, Z3_func_interp a1, unsigned a2);
|
||||
#define LOG_Z3_func_interp_get_entry(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_func_interp_get_entry(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_func_interp_get_else(Z3_context a0, Z3_func_interp a1);
|
||||
#define LOG_Z3_func_interp_get_else(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_func_interp_get_else(_ARG0, _ARG1); }
|
||||
void log_Z3_func_interp_get_arity(Z3_context a0, Z3_func_interp a1);
|
||||
#define LOG_Z3_func_interp_get_arity(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_func_interp_get_arity(_ARG0, _ARG1); }
|
||||
void log_Z3_func_entry_inc_ref(Z3_context a0, Z3_func_entry a1);
|
||||
#define LOG_Z3_func_entry_inc_ref(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_func_entry_inc_ref(_ARG0, _ARG1); }
|
||||
void log_Z3_func_entry_dec_ref(Z3_context a0, Z3_func_entry a1);
|
||||
#define LOG_Z3_func_entry_dec_ref(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_func_entry_dec_ref(_ARG0, _ARG1); }
|
||||
void log_Z3_func_entry_get_value(Z3_context a0, Z3_func_entry a1);
|
||||
#define LOG_Z3_func_entry_get_value(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_func_entry_get_value(_ARG0, _ARG1); }
|
||||
void log_Z3_func_entry_get_num_args(Z3_context a0, Z3_func_entry a1);
|
||||
#define LOG_Z3_func_entry_get_num_args(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_func_entry_get_num_args(_ARG0, _ARG1); }
|
||||
void log_Z3_func_entry_get_arg(Z3_context a0, Z3_func_entry a1, unsigned a2);
|
||||
#define LOG_Z3_func_entry_get_arg(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_func_entry_get_arg(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_get_model_num_constants(Z3_context a0, Z3_model a1);
|
||||
#define LOG_Z3_get_model_num_constants(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_model_num_constants(_ARG0, _ARG1); }
|
||||
void log_Z3_get_model_constant(Z3_context a0, Z3_model a1, unsigned a2);
|
||||
#define LOG_Z3_get_model_constant(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_model_constant(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_eval_func_decl(Z3_context a0, Z3_model a1, Z3_func_decl a2, Z3_ast* a3);
|
||||
#define LOG_Z3_eval_func_decl(_ARG0, _ARG1, _ARG2, _ARG3) z3_log_ctx _LOG_CTX; Z3_ast* Z3ARG3; if (_LOG_CTX.enabled()) { log_Z3_eval_func_decl(_ARG0, _ARG1, _ARG2, _ARG3); Z3ARG3 = _ARG3; }
|
||||
#define RETURN_Z3_eval_func_decl if (_LOG_CTX.enabled()) { SetO((Z3ARG3 == 0 ? 0 : *Z3ARG3), 3); } return
|
||||
void log_Z3_is_array_value(Z3_context a0, Z3_model a1, Z3_ast a2, unsigned* a3);
|
||||
#define LOG_Z3_is_array_value(_ARG0, _ARG1, _ARG2, _ARG3) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_is_array_value(_ARG0, _ARG1, _ARG2, _ARG3); }
|
||||
void log_Z3_get_array_value(Z3_context a0, Z3_model a1, Z3_ast a2, unsigned a3, Z3_ast* a4, Z3_ast* a5, Z3_ast* a6);
|
||||
#define LOG_Z3_get_array_value(_ARG0, _ARG1, _ARG2, _ARG3, _ARG4, _ARG5, _ARG6) z3_log_ctx _LOG_CTX; unsigned Z3ARG3; Z3_ast* Z3ARG4; Z3_ast* Z3ARG5; Z3_ast* Z3ARG6; if (_LOG_CTX.enabled()) { log_Z3_get_array_value(_ARG0, _ARG1, _ARG2, _ARG3, _ARG4, _ARG5, _ARG6); Z3ARG3 = _ARG3; Z3ARG4 = _ARG4; Z3ARG5 = _ARG5; Z3ARG6 = _ARG6; }
|
||||
#define RETURN_Z3_get_array_value if (_LOG_CTX.enabled()) { for (unsigned i = 0; i < Z3ARG3; i++) { SetAO(Z3ARG4[i], 4, i); } for (unsigned i = 0; i < Z3ARG3; i++) { SetAO(Z3ARG5[i], 5, i); } SetO((Z3ARG6 == 0 ? 0 : *Z3ARG6), 6); } return
|
||||
void log_Z3_get_model_num_funcs(Z3_context a0, Z3_model a1);
|
||||
#define LOG_Z3_get_model_num_funcs(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_model_num_funcs(_ARG0, _ARG1); }
|
||||
void log_Z3_get_model_func_decl(Z3_context a0, Z3_model a1, unsigned a2);
|
||||
#define LOG_Z3_get_model_func_decl(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_model_func_decl(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_get_model_func_else(Z3_context a0, Z3_model a1, unsigned a2);
|
||||
#define LOG_Z3_get_model_func_else(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_model_func_else(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_get_model_func_num_entries(Z3_context a0, Z3_model a1, unsigned a2);
|
||||
#define LOG_Z3_get_model_func_num_entries(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_model_func_num_entries(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_get_model_func_entry_num_args(Z3_context a0, Z3_model a1, unsigned a2, unsigned a3);
|
||||
#define LOG_Z3_get_model_func_entry_num_args(_ARG0, _ARG1, _ARG2, _ARG3) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_model_func_entry_num_args(_ARG0, _ARG1, _ARG2, _ARG3); }
|
||||
void log_Z3_get_model_func_entry_arg(Z3_context a0, Z3_model a1, unsigned a2, unsigned a3, unsigned a4);
|
||||
#define LOG_Z3_get_model_func_entry_arg(_ARG0, _ARG1, _ARG2, _ARG3, _ARG4) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_model_func_entry_arg(_ARG0, _ARG1, _ARG2, _ARG3, _ARG4); }
|
||||
void log_Z3_get_model_func_entry_value(Z3_context a0, Z3_model a1, unsigned a2, unsigned a3);
|
||||
#define LOG_Z3_get_model_func_entry_value(_ARG0, _ARG1, _ARG2, _ARG3) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_model_func_entry_value(_ARG0, _ARG1, _ARG2, _ARG3); }
|
||||
void log_Z3_eval(Z3_context a0, Z3_model a1, Z3_ast a2, Z3_ast* a3);
|
||||
#define LOG_Z3_eval(_ARG0, _ARG1, _ARG2, _ARG3) z3_log_ctx _LOG_CTX; Z3_ast* Z3ARG3; if (_LOG_CTX.enabled()) { log_Z3_eval(_ARG0, _ARG1, _ARG2, _ARG3); Z3ARG3 = _ARG3; }
|
||||
#define RETURN_Z3_eval if (_LOG_CTX.enabled()) { SetO((Z3ARG3 == 0 ? 0 : *Z3ARG3), 3); } return
|
||||
void log_Z3_eval_decl(Z3_context a0, Z3_model a1, Z3_func_decl a2, unsigned a3, Z3_ast const * a4, Z3_ast* a5);
|
||||
#define LOG_Z3_eval_decl(_ARG0, _ARG1, _ARG2, _ARG3, _ARG4, _ARG5) z3_log_ctx _LOG_CTX; Z3_ast* Z3ARG5; if (_LOG_CTX.enabled()) { log_Z3_eval_decl(_ARG0, _ARG1, _ARG2, _ARG3, _ARG4, _ARG5); Z3ARG5 = _ARG5; }
|
||||
#define RETURN_Z3_eval_decl if (_LOG_CTX.enabled()) { SetO((Z3ARG5 == 0 ? 0 : *Z3ARG5), 5); } return
|
||||
void log_Z3_set_ast_print_mode(Z3_context a0, Z3_ast_print_mode a1);
|
||||
#define LOG_Z3_set_ast_print_mode(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_set_ast_print_mode(_ARG0, _ARG1); }
|
||||
void log_Z3_ast_to_string(Z3_context a0, Z3_ast a1);
|
||||
#define LOG_Z3_ast_to_string(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_ast_to_string(_ARG0, _ARG1); }
|
||||
void log_Z3_pattern_to_string(Z3_context a0, Z3_pattern a1);
|
||||
#define LOG_Z3_pattern_to_string(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_pattern_to_string(_ARG0, _ARG1); }
|
||||
void log_Z3_sort_to_string(Z3_context a0, Z3_sort a1);
|
||||
#define LOG_Z3_sort_to_string(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_sort_to_string(_ARG0, _ARG1); }
|
||||
void log_Z3_func_decl_to_string(Z3_context a0, Z3_func_decl a1);
|
||||
#define LOG_Z3_func_decl_to_string(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_func_decl_to_string(_ARG0, _ARG1); }
|
||||
void log_Z3_model_to_string(Z3_context a0, Z3_model a1);
|
||||
#define LOG_Z3_model_to_string(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_model_to_string(_ARG0, _ARG1); }
|
||||
void log_Z3_benchmark_to_smtlib_string(Z3_context a0, Z3_string a1, Z3_string a2, Z3_string a3, Z3_string a4, unsigned a5, Z3_ast const * a6, Z3_ast a7);
|
||||
#define LOG_Z3_benchmark_to_smtlib_string(_ARG0, _ARG1, _ARG2, _ARG3, _ARG4, _ARG5, _ARG6, _ARG7) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_benchmark_to_smtlib_string(_ARG0, _ARG1, _ARG2, _ARG3, _ARG4, _ARG5, _ARG6, _ARG7); }
|
||||
void log_Z3_context_to_string(Z3_context a0);
|
||||
#define LOG_Z3_context_to_string(_ARG0) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_context_to_string(_ARG0); }
|
||||
void log_Z3_statistics_to_string(Z3_context a0);
|
||||
#define LOG_Z3_statistics_to_string(_ARG0) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_statistics_to_string(_ARG0); }
|
||||
void log_Z3_get_context_assignment(Z3_context a0);
|
||||
#define LOG_Z3_get_context_assignment(_ARG0) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_context_assignment(_ARG0); }
|
||||
void log_Z3_parse_smtlib_string(Z3_context a0, Z3_string a1, unsigned a2, Z3_symbol const * a3, Z3_sort const * a4, unsigned a5, Z3_symbol const * a6, Z3_func_decl const * a7);
|
||||
#define LOG_Z3_parse_smtlib_string(_ARG0, _ARG1, _ARG2, _ARG3, _ARG4, _ARG5, _ARG6, _ARG7) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_parse_smtlib_string(_ARG0, _ARG1, _ARG2, _ARG3, _ARG4, _ARG5, _ARG6, _ARG7); }
|
||||
void log_Z3_parse_smtlib_file(Z3_context a0, Z3_string a1, unsigned a2, Z3_symbol const * a3, Z3_sort const * a4, unsigned a5, Z3_symbol const * a6, Z3_func_decl const * a7);
|
||||
#define LOG_Z3_parse_smtlib_file(_ARG0, _ARG1, _ARG2, _ARG3, _ARG4, _ARG5, _ARG6, _ARG7) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_parse_smtlib_file(_ARG0, _ARG1, _ARG2, _ARG3, _ARG4, _ARG5, _ARG6, _ARG7); }
|
||||
void log_Z3_get_smtlib_num_formulas(Z3_context a0);
|
||||
#define LOG_Z3_get_smtlib_num_formulas(_ARG0) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_smtlib_num_formulas(_ARG0); }
|
||||
void log_Z3_get_smtlib_formula(Z3_context a0, unsigned a1);
|
||||
#define LOG_Z3_get_smtlib_formula(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_smtlib_formula(_ARG0, _ARG1); }
|
||||
void log_Z3_get_smtlib_num_assumptions(Z3_context a0);
|
||||
#define LOG_Z3_get_smtlib_num_assumptions(_ARG0) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_smtlib_num_assumptions(_ARG0); }
|
||||
void log_Z3_get_smtlib_assumption(Z3_context a0, unsigned a1);
|
||||
#define LOG_Z3_get_smtlib_assumption(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_smtlib_assumption(_ARG0, _ARG1); }
|
||||
void log_Z3_get_smtlib_num_decls(Z3_context a0);
|
||||
#define LOG_Z3_get_smtlib_num_decls(_ARG0) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_smtlib_num_decls(_ARG0); }
|
||||
void log_Z3_get_smtlib_decl(Z3_context a0, unsigned a1);
|
||||
#define LOG_Z3_get_smtlib_decl(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_smtlib_decl(_ARG0, _ARG1); }
|
||||
void log_Z3_get_smtlib_num_sorts(Z3_context a0);
|
||||
#define LOG_Z3_get_smtlib_num_sorts(_ARG0) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_smtlib_num_sorts(_ARG0); }
|
||||
void log_Z3_get_smtlib_sort(Z3_context a0, unsigned a1);
|
||||
#define LOG_Z3_get_smtlib_sort(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_smtlib_sort(_ARG0, _ARG1); }
|
||||
void log_Z3_get_smtlib_error(Z3_context a0);
|
||||
#define LOG_Z3_get_smtlib_error(_ARG0) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_smtlib_error(_ARG0); }
|
||||
void log_Z3_parse_z3_string(Z3_context a0, Z3_string a1);
|
||||
#define LOG_Z3_parse_z3_string(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_parse_z3_string(_ARG0, _ARG1); }
|
||||
void log_Z3_parse_z3_file(Z3_context a0, Z3_string a1);
|
||||
#define LOG_Z3_parse_z3_file(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_parse_z3_file(_ARG0, _ARG1); }
|
||||
void log_Z3_parse_smtlib2_string(Z3_context a0, Z3_string a1, unsigned a2, Z3_symbol const * a3, Z3_sort const * a4, unsigned a5, Z3_symbol const * a6, Z3_func_decl const * a7);
|
||||
#define LOG_Z3_parse_smtlib2_string(_ARG0, _ARG1, _ARG2, _ARG3, _ARG4, _ARG5, _ARG6, _ARG7) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_parse_smtlib2_string(_ARG0, _ARG1, _ARG2, _ARG3, _ARG4, _ARG5, _ARG6, _ARG7); }
|
||||
void log_Z3_parse_smtlib2_file(Z3_context a0, Z3_string a1, unsigned a2, Z3_symbol const * a3, Z3_sort const * a4, unsigned a5, Z3_symbol const * a6, Z3_func_decl const * a7);
|
||||
#define LOG_Z3_parse_smtlib2_file(_ARG0, _ARG1, _ARG2, _ARG3, _ARG4, _ARG5, _ARG6, _ARG7) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_parse_smtlib2_file(_ARG0, _ARG1, _ARG2, _ARG3, _ARG4, _ARG5, _ARG6, _ARG7); }
|
||||
void log_Z3_get_error_code(Z3_context a0);
|
||||
#define LOG_Z3_get_error_code(_ARG0) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_error_code(_ARG0); }
|
||||
void log_Z3_set_error(Z3_context a0, Z3_error_code a1);
|
||||
#define LOG_Z3_set_error(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_set_error(_ARG0, _ARG1); }
|
||||
void log_Z3_get_error_msg(Z3_error_code a0);
|
||||
#define LOG_Z3_get_error_msg(_ARG0) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_error_msg(_ARG0); }
|
||||
void log_Z3_get_version(unsigned* a0, unsigned* a1, unsigned* a2, unsigned* a3);
|
||||
#define LOG_Z3_get_version(_ARG0, _ARG1, _ARG2, _ARG3) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_version(_ARG0, _ARG1, _ARG2, _ARG3); }
|
||||
void log_Z3_reset_memory();
|
||||
#define LOG_Z3_reset_memory() z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_reset_memory(); }
|
||||
void log_Z3_is_app(Z3_context a0, Z3_ast a1);
|
||||
#define LOG_Z3_is_app(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_is_app(_ARG0, _ARG1); }
|
||||
void log_Z3_is_numeral_ast(Z3_context a0, Z3_ast a1);
|
||||
#define LOG_Z3_is_numeral_ast(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_is_numeral_ast(_ARG0, _ARG1); }
|
||||
void log_Z3_get_arity(Z3_context a0, Z3_func_decl a1);
|
||||
#define LOG_Z3_get_arity(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_arity(_ARG0, _ARG1); }
|
||||
void log_Z3_mk_injective_function(Z3_context a0, Z3_symbol a1, unsigned a2, Z3_sort const * a3, Z3_sort a4);
|
||||
#define LOG_Z3_mk_injective_function(_ARG0, _ARG1, _ARG2, _ARG3, _ARG4) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_injective_function(_ARG0, _ARG1, _ARG2, _ARG3, _ARG4); }
|
||||
void log_Z3_mk_fixedpoint(Z3_context a0);
|
||||
#define LOG_Z3_mk_fixedpoint(_ARG0) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_fixedpoint(_ARG0); }
|
||||
void log_Z3_fixedpoint_inc_ref(Z3_context a0, Z3_fixedpoint a1);
|
||||
#define LOG_Z3_fixedpoint_inc_ref(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_fixedpoint_inc_ref(_ARG0, _ARG1); }
|
||||
void log_Z3_fixedpoint_dec_ref(Z3_context a0, Z3_fixedpoint a1);
|
||||
#define LOG_Z3_fixedpoint_dec_ref(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_fixedpoint_dec_ref(_ARG0, _ARG1); }
|
||||
void log_Z3_fixedpoint_push(Z3_context a0, Z3_fixedpoint a1);
|
||||
#define LOG_Z3_fixedpoint_push(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_fixedpoint_push(_ARG0, _ARG1); }
|
||||
void log_Z3_fixedpoint_pop(Z3_context a0, Z3_fixedpoint a1);
|
||||
#define LOG_Z3_fixedpoint_pop(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_fixedpoint_pop(_ARG0, _ARG1); }
|
||||
void log_Z3_fixedpoint_register_relation(Z3_context a0, Z3_fixedpoint a1, Z3_func_decl a2);
|
||||
#define LOG_Z3_fixedpoint_register_relation(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_fixedpoint_register_relation(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_fixedpoint_assert(Z3_context a0, Z3_fixedpoint a1, Z3_ast a2);
|
||||
#define LOG_Z3_fixedpoint_assert(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_fixedpoint_assert(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_fixedpoint_add_rule(Z3_context a0, Z3_fixedpoint a1, Z3_ast a2, Z3_symbol a3);
|
||||
#define LOG_Z3_fixedpoint_add_rule(_ARG0, _ARG1, _ARG2, _ARG3) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_fixedpoint_add_rule(_ARG0, _ARG1, _ARG2, _ARG3); }
|
||||
void log_Z3_fixedpoint_add_fact(Z3_context a0, Z3_fixedpoint a1, Z3_func_decl a2, unsigned a3, unsigned const * a4);
|
||||
#define LOG_Z3_fixedpoint_add_fact(_ARG0, _ARG1, _ARG2, _ARG3, _ARG4) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_fixedpoint_add_fact(_ARG0, _ARG1, _ARG2, _ARG3, _ARG4); }
|
||||
void log_Z3_fixedpoint_query(Z3_context a0, Z3_fixedpoint a1, Z3_ast a2);
|
||||
#define LOG_Z3_fixedpoint_query(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_fixedpoint_query(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_fixedpoint_query_relations(Z3_context a0, Z3_fixedpoint a1, unsigned a2, Z3_func_decl const * a3);
|
||||
#define LOG_Z3_fixedpoint_query_relations(_ARG0, _ARG1, _ARG2, _ARG3) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_fixedpoint_query_relations(_ARG0, _ARG1, _ARG2, _ARG3); }
|
||||
void log_Z3_fixedpoint_get_answer(Z3_context a0, Z3_fixedpoint a1);
|
||||
#define LOG_Z3_fixedpoint_get_answer(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_fixedpoint_get_answer(_ARG0, _ARG1); }
|
||||
void log_Z3_fixedpoint_update_rule(Z3_context a0, Z3_fixedpoint a1, Z3_ast a2, Z3_symbol a3);
|
||||
#define LOG_Z3_fixedpoint_update_rule(_ARG0, _ARG1, _ARG2, _ARG3) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_fixedpoint_update_rule(_ARG0, _ARG1, _ARG2, _ARG3); }
|
||||
void log_Z3_fixedpoint_get_num_levels(Z3_context a0, Z3_fixedpoint a1, Z3_func_decl a2);
|
||||
#define LOG_Z3_fixedpoint_get_num_levels(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_fixedpoint_get_num_levels(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_fixedpoint_get_cover_delta(Z3_context a0, Z3_fixedpoint a1, int a2, Z3_func_decl a3);
|
||||
#define LOG_Z3_fixedpoint_get_cover_delta(_ARG0, _ARG1, _ARG2, _ARG3) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_fixedpoint_get_cover_delta(_ARG0, _ARG1, _ARG2, _ARG3); }
|
||||
void log_Z3_fixedpoint_add_cover(Z3_context a0, Z3_fixedpoint a1, int a2, Z3_func_decl a3, Z3_ast a4);
|
||||
#define LOG_Z3_fixedpoint_add_cover(_ARG0, _ARG1, _ARG2, _ARG3, _ARG4) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_fixedpoint_add_cover(_ARG0, _ARG1, _ARG2, _ARG3, _ARG4); }
|
||||
void log_Z3_fixedpoint_get_statistics(Z3_context a0, Z3_fixedpoint a1);
|
||||
#define LOG_Z3_fixedpoint_get_statistics(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_fixedpoint_get_statistics(_ARG0, _ARG1); }
|
||||
void log_Z3_fixedpoint_get_help(Z3_context a0, Z3_fixedpoint a1);
|
||||
#define LOG_Z3_fixedpoint_get_help(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_fixedpoint_get_help(_ARG0, _ARG1); }
|
||||
void log_Z3_fixedpoint_get_param_descrs(Z3_context a0, Z3_fixedpoint a1);
|
||||
#define LOG_Z3_fixedpoint_get_param_descrs(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_fixedpoint_get_param_descrs(_ARG0, _ARG1); }
|
||||
void log_Z3_fixedpoint_set_params(Z3_context a0, Z3_fixedpoint a1, Z3_params a2);
|
||||
#define LOG_Z3_fixedpoint_set_params(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_fixedpoint_set_params(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_fixedpoint_to_string(Z3_context a0, Z3_fixedpoint a1, unsigned a2, Z3_ast const * a3);
|
||||
#define LOG_Z3_fixedpoint_to_string(_ARG0, _ARG1, _ARG2, _ARG3) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_fixedpoint_to_string(_ARG0, _ARG1, _ARG2, _ARG3); }
|
||||
void log_Z3_fixedpoint_get_reason_unknown(Z3_context a0, Z3_fixedpoint a1);
|
||||
#define LOG_Z3_fixedpoint_get_reason_unknown(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_fixedpoint_get_reason_unknown(_ARG0, _ARG1); }
|
||||
void log_Z3_fixedpoint_set_predicate_representation(Z3_context a0, Z3_fixedpoint a1, Z3_func_decl a2, unsigned a3, Z3_symbol const * a4);
|
||||
#define LOG_Z3_fixedpoint_set_predicate_representation(_ARG0, _ARG1, _ARG2, _ARG3, _ARG4) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_fixedpoint_set_predicate_representation(_ARG0, _ARG1, _ARG2, _ARG3, _ARG4); }
|
||||
void log_Z3_fixedpoint_simplify_rules(Z3_context a0, Z3_fixedpoint a1, unsigned a2, Z3_ast const * a3, unsigned a4, Z3_func_decl const * a5);
|
||||
#define LOG_Z3_fixedpoint_simplify_rules(_ARG0, _ARG1, _ARG2, _ARG3, _ARG4, _ARG5) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_fixedpoint_simplify_rules(_ARG0, _ARG1, _ARG2, _ARG3, _ARG4, _ARG5); }
|
||||
void log_Z3_mk_params(Z3_context a0);
|
||||
#define LOG_Z3_mk_params(_ARG0) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_params(_ARG0); }
|
||||
void log_Z3_params_inc_ref(Z3_context a0, Z3_params a1);
|
||||
#define LOG_Z3_params_inc_ref(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_params_inc_ref(_ARG0, _ARG1); }
|
||||
void log_Z3_params_dec_ref(Z3_context a0, Z3_params a1);
|
||||
#define LOG_Z3_params_dec_ref(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_params_dec_ref(_ARG0, _ARG1); }
|
||||
void log_Z3_params_set_bool(Z3_context a0, Z3_params a1, Z3_symbol a2, Z3_bool a3);
|
||||
#define LOG_Z3_params_set_bool(_ARG0, _ARG1, _ARG2, _ARG3) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_params_set_bool(_ARG0, _ARG1, _ARG2, _ARG3); }
|
||||
void log_Z3_params_set_uint(Z3_context a0, Z3_params a1, Z3_symbol a2, unsigned a3);
|
||||
#define LOG_Z3_params_set_uint(_ARG0, _ARG1, _ARG2, _ARG3) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_params_set_uint(_ARG0, _ARG1, _ARG2, _ARG3); }
|
||||
void log_Z3_params_set_double(Z3_context a0, Z3_params a1, Z3_symbol a2, double a3);
|
||||
#define LOG_Z3_params_set_double(_ARG0, _ARG1, _ARG2, _ARG3) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_params_set_double(_ARG0, _ARG1, _ARG2, _ARG3); }
|
||||
void log_Z3_params_set_symbol(Z3_context a0, Z3_params a1, Z3_symbol a2, Z3_symbol a3);
|
||||
#define LOG_Z3_params_set_symbol(_ARG0, _ARG1, _ARG2, _ARG3) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_params_set_symbol(_ARG0, _ARG1, _ARG2, _ARG3); }
|
||||
void log_Z3_params_to_string(Z3_context a0, Z3_params a1);
|
||||
#define LOG_Z3_params_to_string(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_params_to_string(_ARG0, _ARG1); }
|
||||
void log_Z3_params_validate(Z3_context a0, Z3_params a1, Z3_param_descrs a2);
|
||||
#define LOG_Z3_params_validate(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_params_validate(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_param_descrs_inc_ref(Z3_context a0, Z3_param_descrs a1);
|
||||
#define LOG_Z3_param_descrs_inc_ref(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_param_descrs_inc_ref(_ARG0, _ARG1); }
|
||||
void log_Z3_param_descrs_dec_ref(Z3_context a0, Z3_param_descrs a1);
|
||||
#define LOG_Z3_param_descrs_dec_ref(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_param_descrs_dec_ref(_ARG0, _ARG1); }
|
||||
void log_Z3_param_descrs_get_kind(Z3_context a0, Z3_param_descrs a1, Z3_symbol a2);
|
||||
#define LOG_Z3_param_descrs_get_kind(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_param_descrs_get_kind(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_param_descrs_size(Z3_context a0, Z3_param_descrs a1);
|
||||
#define LOG_Z3_param_descrs_size(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_param_descrs_size(_ARG0, _ARG1); }
|
||||
void log_Z3_param_descrs_get_name(Z3_context a0, Z3_param_descrs a1, unsigned a2);
|
||||
#define LOG_Z3_param_descrs_get_name(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_param_descrs_get_name(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_interrupt(Z3_context a0);
|
||||
#define LOG_Z3_interrupt(_ARG0) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_interrupt(_ARG0); }
|
||||
void log_Z3_get_error_msg_ex(Z3_context a0, Z3_error_code a1);
|
||||
#define LOG_Z3_get_error_msg_ex(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_error_msg_ex(_ARG0, _ARG1); }
|
||||
void log_Z3_translate(Z3_context a0, Z3_ast a1, Z3_context a2);
|
||||
#define LOG_Z3_translate(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_translate(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_goal(Z3_context a0, Z3_bool a1, Z3_bool a2, Z3_bool a3);
|
||||
#define LOG_Z3_mk_goal(_ARG0, _ARG1, _ARG2, _ARG3) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_goal(_ARG0, _ARG1, _ARG2, _ARG3); }
|
||||
void log_Z3_goal_inc_ref(Z3_context a0, Z3_goal a1);
|
||||
#define LOG_Z3_goal_inc_ref(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_goal_inc_ref(_ARG0, _ARG1); }
|
||||
void log_Z3_goal_dec_ref(Z3_context a0, Z3_goal a1);
|
||||
#define LOG_Z3_goal_dec_ref(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_goal_dec_ref(_ARG0, _ARG1); }
|
||||
void log_Z3_goal_precision(Z3_context a0, Z3_goal a1);
|
||||
#define LOG_Z3_goal_precision(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_goal_precision(_ARG0, _ARG1); }
|
||||
void log_Z3_goal_assert(Z3_context a0, Z3_goal a1, Z3_ast a2);
|
||||
#define LOG_Z3_goal_assert(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_goal_assert(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_goal_inconsistent(Z3_context a0, Z3_goal a1);
|
||||
#define LOG_Z3_goal_inconsistent(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_goal_inconsistent(_ARG0, _ARG1); }
|
||||
void log_Z3_goal_depth(Z3_context a0, Z3_goal a1);
|
||||
#define LOG_Z3_goal_depth(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_goal_depth(_ARG0, _ARG1); }
|
||||
void log_Z3_goal_reset(Z3_context a0, Z3_goal a1);
|
||||
#define LOG_Z3_goal_reset(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_goal_reset(_ARG0, _ARG1); }
|
||||
void log_Z3_goal_size(Z3_context a0, Z3_goal a1);
|
||||
#define LOG_Z3_goal_size(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_goal_size(_ARG0, _ARG1); }
|
||||
void log_Z3_goal_formula(Z3_context a0, Z3_goal a1, unsigned a2);
|
||||
#define LOG_Z3_goal_formula(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_goal_formula(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_goal_num_exprs(Z3_context a0, Z3_goal a1);
|
||||
#define LOG_Z3_goal_num_exprs(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_goal_num_exprs(_ARG0, _ARG1); }
|
||||
void log_Z3_goal_is_decided_sat(Z3_context a0, Z3_goal a1);
|
||||
#define LOG_Z3_goal_is_decided_sat(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_goal_is_decided_sat(_ARG0, _ARG1); }
|
||||
void log_Z3_goal_is_decided_unsat(Z3_context a0, Z3_goal a1);
|
||||
#define LOG_Z3_goal_is_decided_unsat(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_goal_is_decided_unsat(_ARG0, _ARG1); }
|
||||
void log_Z3_goal_translate(Z3_context a0, Z3_goal a1, Z3_context a2);
|
||||
#define LOG_Z3_goal_translate(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_goal_translate(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_goal_to_string(Z3_context a0, Z3_goal a1);
|
||||
#define LOG_Z3_goal_to_string(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_goal_to_string(_ARG0, _ARG1); }
|
||||
void log_Z3_mk_tactic(Z3_context a0, Z3_string a1);
|
||||
#define LOG_Z3_mk_tactic(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_tactic(_ARG0, _ARG1); }
|
||||
void log_Z3_mk_probe(Z3_context a0, Z3_string a1);
|
||||
#define LOG_Z3_mk_probe(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_probe(_ARG0, _ARG1); }
|
||||
void log_Z3_tactic_inc_ref(Z3_context a0, Z3_tactic a1);
|
||||
#define LOG_Z3_tactic_inc_ref(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_tactic_inc_ref(_ARG0, _ARG1); }
|
||||
void log_Z3_tactic_dec_ref(Z3_context a0, Z3_tactic a1);
|
||||
#define LOG_Z3_tactic_dec_ref(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_tactic_dec_ref(_ARG0, _ARG1); }
|
||||
void log_Z3_probe_inc_ref(Z3_context a0, Z3_probe a1);
|
||||
#define LOG_Z3_probe_inc_ref(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_probe_inc_ref(_ARG0, _ARG1); }
|
||||
void log_Z3_probe_dec_ref(Z3_context a0, Z3_probe a1);
|
||||
#define LOG_Z3_probe_dec_ref(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_probe_dec_ref(_ARG0, _ARG1); }
|
||||
void log_Z3_tactic_and_then(Z3_context a0, Z3_tactic a1, Z3_tactic a2);
|
||||
#define LOG_Z3_tactic_and_then(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_tactic_and_then(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_tactic_or_else(Z3_context a0, Z3_tactic a1, Z3_tactic a2);
|
||||
#define LOG_Z3_tactic_or_else(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_tactic_or_else(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_tactic_par_or(Z3_context a0, unsigned a1, Z3_tactic const * a2);
|
||||
#define LOG_Z3_tactic_par_or(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_tactic_par_or(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_tactic_par_and_then(Z3_context a0, Z3_tactic a1, Z3_tactic a2);
|
||||
#define LOG_Z3_tactic_par_and_then(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_tactic_par_and_then(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_tactic_try_for(Z3_context a0, Z3_tactic a1, unsigned a2);
|
||||
#define LOG_Z3_tactic_try_for(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_tactic_try_for(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_tactic_when(Z3_context a0, Z3_probe a1, Z3_tactic a2);
|
||||
#define LOG_Z3_tactic_when(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_tactic_when(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_tactic_cond(Z3_context a0, Z3_probe a1, Z3_tactic a2, Z3_tactic a3);
|
||||
#define LOG_Z3_tactic_cond(_ARG0, _ARG1, _ARG2, _ARG3) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_tactic_cond(_ARG0, _ARG1, _ARG2, _ARG3); }
|
||||
void log_Z3_tactic_repeat(Z3_context a0, Z3_tactic a1, unsigned a2);
|
||||
#define LOG_Z3_tactic_repeat(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_tactic_repeat(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_tactic_skip(Z3_context a0);
|
||||
#define LOG_Z3_tactic_skip(_ARG0) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_tactic_skip(_ARG0); }
|
||||
void log_Z3_tactic_fail(Z3_context a0);
|
||||
#define LOG_Z3_tactic_fail(_ARG0) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_tactic_fail(_ARG0); }
|
||||
void log_Z3_tactic_fail_if(Z3_context a0, Z3_probe a1);
|
||||
#define LOG_Z3_tactic_fail_if(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_tactic_fail_if(_ARG0, _ARG1); }
|
||||
void log_Z3_tactic_fail_if_not_decided(Z3_context a0);
|
||||
#define LOG_Z3_tactic_fail_if_not_decided(_ARG0) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_tactic_fail_if_not_decided(_ARG0); }
|
||||
void log_Z3_tactic_using_params(Z3_context a0, Z3_tactic a1, Z3_params a2);
|
||||
#define LOG_Z3_tactic_using_params(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_tactic_using_params(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_probe_const(Z3_context a0, double a1);
|
||||
#define LOG_Z3_probe_const(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_probe_const(_ARG0, _ARG1); }
|
||||
void log_Z3_probe_lt(Z3_context a0, Z3_probe a1, Z3_probe a2);
|
||||
#define LOG_Z3_probe_lt(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_probe_lt(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_probe_le(Z3_context a0, Z3_probe a1, Z3_probe a2);
|
||||
#define LOG_Z3_probe_le(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_probe_le(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_probe_gt(Z3_context a0, Z3_probe a1, Z3_probe a2);
|
||||
#define LOG_Z3_probe_gt(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_probe_gt(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_probe_ge(Z3_context a0, Z3_probe a1, Z3_probe a2);
|
||||
#define LOG_Z3_probe_ge(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_probe_ge(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_probe_eq(Z3_context a0, Z3_probe a1, Z3_probe a2);
|
||||
#define LOG_Z3_probe_eq(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_probe_eq(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_probe_and(Z3_context a0, Z3_probe a1, Z3_probe a2);
|
||||
#define LOG_Z3_probe_and(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_probe_and(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_probe_or(Z3_context a0, Z3_probe a1, Z3_probe a2);
|
||||
#define LOG_Z3_probe_or(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_probe_or(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_probe_not(Z3_context a0, Z3_probe a1);
|
||||
#define LOG_Z3_probe_not(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_probe_not(_ARG0, _ARG1); }
|
||||
void log_Z3_get_num_tactics(Z3_context a0);
|
||||
#define LOG_Z3_get_num_tactics(_ARG0) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_num_tactics(_ARG0); }
|
||||
void log_Z3_get_tactic_name(Z3_context a0, unsigned a1);
|
||||
#define LOG_Z3_get_tactic_name(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_tactic_name(_ARG0, _ARG1); }
|
||||
void log_Z3_get_num_probes(Z3_context a0);
|
||||
#define LOG_Z3_get_num_probes(_ARG0) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_num_probes(_ARG0); }
|
||||
void log_Z3_get_probe_name(Z3_context a0, unsigned a1);
|
||||
#define LOG_Z3_get_probe_name(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_get_probe_name(_ARG0, _ARG1); }
|
||||
void log_Z3_tactic_get_help(Z3_context a0, Z3_tactic a1);
|
||||
#define LOG_Z3_tactic_get_help(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_tactic_get_help(_ARG0, _ARG1); }
|
||||
void log_Z3_tactic_get_param_descrs(Z3_context a0, Z3_tactic a1);
|
||||
#define LOG_Z3_tactic_get_param_descrs(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_tactic_get_param_descrs(_ARG0, _ARG1); }
|
||||
void log_Z3_tactic_get_descr(Z3_context a0, Z3_string a1);
|
||||
#define LOG_Z3_tactic_get_descr(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_tactic_get_descr(_ARG0, _ARG1); }
|
||||
void log_Z3_probe_get_descr(Z3_context a0, Z3_string a1);
|
||||
#define LOG_Z3_probe_get_descr(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_probe_get_descr(_ARG0, _ARG1); }
|
||||
void log_Z3_probe_apply(Z3_context a0, Z3_probe a1, Z3_goal a2);
|
||||
#define LOG_Z3_probe_apply(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_probe_apply(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_tactic_apply(Z3_context a0, Z3_tactic a1, Z3_goal a2);
|
||||
#define LOG_Z3_tactic_apply(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_tactic_apply(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_tactic_apply_ex(Z3_context a0, Z3_tactic a1, Z3_goal a2, Z3_params a3);
|
||||
#define LOG_Z3_tactic_apply_ex(_ARG0, _ARG1, _ARG2, _ARG3) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_tactic_apply_ex(_ARG0, _ARG1, _ARG2, _ARG3); }
|
||||
void log_Z3_apply_result_inc_ref(Z3_context a0, Z3_apply_result a1);
|
||||
#define LOG_Z3_apply_result_inc_ref(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_apply_result_inc_ref(_ARG0, _ARG1); }
|
||||
void log_Z3_apply_result_dec_ref(Z3_context a0, Z3_apply_result a1);
|
||||
#define LOG_Z3_apply_result_dec_ref(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_apply_result_dec_ref(_ARG0, _ARG1); }
|
||||
void log_Z3_apply_result_to_string(Z3_context a0, Z3_apply_result a1);
|
||||
#define LOG_Z3_apply_result_to_string(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_apply_result_to_string(_ARG0, _ARG1); }
|
||||
void log_Z3_apply_result_get_num_subgoals(Z3_context a0, Z3_apply_result a1);
|
||||
#define LOG_Z3_apply_result_get_num_subgoals(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_apply_result_get_num_subgoals(_ARG0, _ARG1); }
|
||||
void log_Z3_apply_result_get_subgoal(Z3_context a0, Z3_apply_result a1, unsigned a2);
|
||||
#define LOG_Z3_apply_result_get_subgoal(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_apply_result_get_subgoal(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_apply_result_convert_model(Z3_context a0, Z3_apply_result a1, unsigned a2, Z3_model a3);
|
||||
#define LOG_Z3_apply_result_convert_model(_ARG0, _ARG1, _ARG2, _ARG3) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_apply_result_convert_model(_ARG0, _ARG1, _ARG2, _ARG3); }
|
||||
void log_Z3_mk_solver(Z3_context a0);
|
||||
#define LOG_Z3_mk_solver(_ARG0) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_solver(_ARG0); }
|
||||
void log_Z3_mk_simple_solver(Z3_context a0);
|
||||
#define LOG_Z3_mk_simple_solver(_ARG0) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_simple_solver(_ARG0); }
|
||||
void log_Z3_mk_solver_for_logic(Z3_context a0, Z3_symbol a1);
|
||||
#define LOG_Z3_mk_solver_for_logic(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_solver_for_logic(_ARG0, _ARG1); }
|
||||
void log_Z3_mk_solver_from_tactic(Z3_context a0, Z3_tactic a1);
|
||||
#define LOG_Z3_mk_solver_from_tactic(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_solver_from_tactic(_ARG0, _ARG1); }
|
||||
void log_Z3_solver_get_help(Z3_context a0, Z3_solver a1);
|
||||
#define LOG_Z3_solver_get_help(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_solver_get_help(_ARG0, _ARG1); }
|
||||
void log_Z3_solver_get_param_descrs(Z3_context a0, Z3_solver a1);
|
||||
#define LOG_Z3_solver_get_param_descrs(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_solver_get_param_descrs(_ARG0, _ARG1); }
|
||||
void log_Z3_solver_set_params(Z3_context a0, Z3_solver a1, Z3_params a2);
|
||||
#define LOG_Z3_solver_set_params(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_solver_set_params(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_solver_inc_ref(Z3_context a0, Z3_solver a1);
|
||||
#define LOG_Z3_solver_inc_ref(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_solver_inc_ref(_ARG0, _ARG1); }
|
||||
void log_Z3_solver_dec_ref(Z3_context a0, Z3_solver a1);
|
||||
#define LOG_Z3_solver_dec_ref(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_solver_dec_ref(_ARG0, _ARG1); }
|
||||
void log_Z3_solver_push(Z3_context a0, Z3_solver a1);
|
||||
#define LOG_Z3_solver_push(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_solver_push(_ARG0, _ARG1); }
|
||||
void log_Z3_solver_pop(Z3_context a0, Z3_solver a1, unsigned a2);
|
||||
#define LOG_Z3_solver_pop(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_solver_pop(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_solver_reset(Z3_context a0, Z3_solver a1);
|
||||
#define LOG_Z3_solver_reset(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_solver_reset(_ARG0, _ARG1); }
|
||||
void log_Z3_solver_get_num_scopes(Z3_context a0, Z3_solver a1);
|
||||
#define LOG_Z3_solver_get_num_scopes(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_solver_get_num_scopes(_ARG0, _ARG1); }
|
||||
void log_Z3_solver_assert(Z3_context a0, Z3_solver a1, Z3_ast a2);
|
||||
#define LOG_Z3_solver_assert(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_solver_assert(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_solver_get_assertions(Z3_context a0, Z3_solver a1);
|
||||
#define LOG_Z3_solver_get_assertions(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_solver_get_assertions(_ARG0, _ARG1); }
|
||||
void log_Z3_solver_check(Z3_context a0, Z3_solver a1);
|
||||
#define LOG_Z3_solver_check(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_solver_check(_ARG0, _ARG1); }
|
||||
void log_Z3_solver_check_assumptions(Z3_context a0, Z3_solver a1, unsigned a2, Z3_ast const * a3);
|
||||
#define LOG_Z3_solver_check_assumptions(_ARG0, _ARG1, _ARG2, _ARG3) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_solver_check_assumptions(_ARG0, _ARG1, _ARG2, _ARG3); }
|
||||
void log_Z3_solver_get_model(Z3_context a0, Z3_solver a1);
|
||||
#define LOG_Z3_solver_get_model(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_solver_get_model(_ARG0, _ARG1); }
|
||||
void log_Z3_solver_get_proof(Z3_context a0, Z3_solver a1);
|
||||
#define LOG_Z3_solver_get_proof(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_solver_get_proof(_ARG0, _ARG1); }
|
||||
void log_Z3_solver_get_unsat_core(Z3_context a0, Z3_solver a1);
|
||||
#define LOG_Z3_solver_get_unsat_core(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_solver_get_unsat_core(_ARG0, _ARG1); }
|
||||
void log_Z3_solver_get_reason_unknown(Z3_context a0, Z3_solver a1);
|
||||
#define LOG_Z3_solver_get_reason_unknown(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_solver_get_reason_unknown(_ARG0, _ARG1); }
|
||||
void log_Z3_solver_get_statistics(Z3_context a0, Z3_solver a1);
|
||||
#define LOG_Z3_solver_get_statistics(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_solver_get_statistics(_ARG0, _ARG1); }
|
||||
void log_Z3_solver_to_string(Z3_context a0, Z3_solver a1);
|
||||
#define LOG_Z3_solver_to_string(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_solver_to_string(_ARG0, _ARG1); }
|
||||
void log_Z3_stats_to_string(Z3_context a0, Z3_stats a1);
|
||||
#define LOG_Z3_stats_to_string(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_stats_to_string(_ARG0, _ARG1); }
|
||||
void log_Z3_stats_inc_ref(Z3_context a0, Z3_stats a1);
|
||||
#define LOG_Z3_stats_inc_ref(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_stats_inc_ref(_ARG0, _ARG1); }
|
||||
void log_Z3_stats_dec_ref(Z3_context a0, Z3_stats a1);
|
||||
#define LOG_Z3_stats_dec_ref(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_stats_dec_ref(_ARG0, _ARG1); }
|
||||
void log_Z3_stats_size(Z3_context a0, Z3_stats a1);
|
||||
#define LOG_Z3_stats_size(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_stats_size(_ARG0, _ARG1); }
|
||||
void log_Z3_stats_get_key(Z3_context a0, Z3_stats a1, unsigned a2);
|
||||
#define LOG_Z3_stats_get_key(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_stats_get_key(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_stats_is_uint(Z3_context a0, Z3_stats a1, unsigned a2);
|
||||
#define LOG_Z3_stats_is_uint(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_stats_is_uint(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_stats_is_double(Z3_context a0, Z3_stats a1, unsigned a2);
|
||||
#define LOG_Z3_stats_is_double(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_stats_is_double(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_stats_get_uint_value(Z3_context a0, Z3_stats a1, unsigned a2);
|
||||
#define LOG_Z3_stats_get_uint_value(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_stats_get_uint_value(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_stats_get_double_value(Z3_context a0, Z3_stats a1, unsigned a2);
|
||||
#define LOG_Z3_stats_get_double_value(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_stats_get_double_value(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_mk_ast_vector(Z3_context a0);
|
||||
#define LOG_Z3_mk_ast_vector(_ARG0) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_ast_vector(_ARG0); }
|
||||
void log_Z3_ast_vector_inc_ref(Z3_context a0, Z3_ast_vector a1);
|
||||
#define LOG_Z3_ast_vector_inc_ref(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_ast_vector_inc_ref(_ARG0, _ARG1); }
|
||||
void log_Z3_ast_vector_dec_ref(Z3_context a0, Z3_ast_vector a1);
|
||||
#define LOG_Z3_ast_vector_dec_ref(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_ast_vector_dec_ref(_ARG0, _ARG1); }
|
||||
void log_Z3_ast_vector_size(Z3_context a0, Z3_ast_vector a1);
|
||||
#define LOG_Z3_ast_vector_size(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_ast_vector_size(_ARG0, _ARG1); }
|
||||
void log_Z3_ast_vector_get(Z3_context a0, Z3_ast_vector a1, unsigned a2);
|
||||
#define LOG_Z3_ast_vector_get(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_ast_vector_get(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_ast_vector_set(Z3_context a0, Z3_ast_vector a1, unsigned a2, Z3_ast a3);
|
||||
#define LOG_Z3_ast_vector_set(_ARG0, _ARG1, _ARG2, _ARG3) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_ast_vector_set(_ARG0, _ARG1, _ARG2, _ARG3); }
|
||||
void log_Z3_ast_vector_resize(Z3_context a0, Z3_ast_vector a1, unsigned a2);
|
||||
#define LOG_Z3_ast_vector_resize(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_ast_vector_resize(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_ast_vector_push(Z3_context a0, Z3_ast_vector a1, Z3_ast a2);
|
||||
#define LOG_Z3_ast_vector_push(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_ast_vector_push(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_ast_vector_translate(Z3_context a0, Z3_ast_vector a1, Z3_context a2);
|
||||
#define LOG_Z3_ast_vector_translate(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_ast_vector_translate(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_ast_vector_to_string(Z3_context a0, Z3_ast_vector a1);
|
||||
#define LOG_Z3_ast_vector_to_string(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_ast_vector_to_string(_ARG0, _ARG1); }
|
||||
void log_Z3_mk_ast_map(Z3_context a0);
|
||||
#define LOG_Z3_mk_ast_map(_ARG0) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_ast_map(_ARG0); }
|
||||
void log_Z3_ast_map_inc_ref(Z3_context a0, Z3_ast_map a1);
|
||||
#define LOG_Z3_ast_map_inc_ref(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_ast_map_inc_ref(_ARG0, _ARG1); }
|
||||
void log_Z3_ast_map_dec_ref(Z3_context a0, Z3_ast_map a1);
|
||||
#define LOG_Z3_ast_map_dec_ref(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_ast_map_dec_ref(_ARG0, _ARG1); }
|
||||
void log_Z3_ast_map_contains(Z3_context a0, Z3_ast_map a1, Z3_ast a2);
|
||||
#define LOG_Z3_ast_map_contains(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_ast_map_contains(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_ast_map_find(Z3_context a0, Z3_ast_map a1, Z3_ast a2);
|
||||
#define LOG_Z3_ast_map_find(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_ast_map_find(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_ast_map_insert(Z3_context a0, Z3_ast_map a1, Z3_ast a2, Z3_ast a3);
|
||||
#define LOG_Z3_ast_map_insert(_ARG0, _ARG1, _ARG2, _ARG3) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_ast_map_insert(_ARG0, _ARG1, _ARG2, _ARG3); }
|
||||
void log_Z3_ast_map_erase(Z3_context a0, Z3_ast_map a1, Z3_ast a2);
|
||||
#define LOG_Z3_ast_map_erase(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_ast_map_erase(_ARG0, _ARG1, _ARG2); }
|
||||
void log_Z3_ast_map_size(Z3_context a0, Z3_ast_map a1);
|
||||
#define LOG_Z3_ast_map_size(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_ast_map_size(_ARG0, _ARG1); }
|
||||
void log_Z3_ast_map_reset(Z3_context a0, Z3_ast_map a1);
|
||||
#define LOG_Z3_ast_map_reset(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_ast_map_reset(_ARG0, _ARG1); }
|
||||
void log_Z3_ast_map_keys(Z3_context a0, Z3_ast_map a1);
|
||||
#define LOG_Z3_ast_map_keys(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_ast_map_keys(_ARG0, _ARG1); }
|
||||
void log_Z3_ast_map_to_string(Z3_context a0, Z3_ast_map a1);
|
||||
#define LOG_Z3_ast_map_to_string(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_ast_map_to_string(_ARG0, _ARG1); }
|
670
lib/api_model.cpp
Normal file
670
lib/api_model.cpp
Normal file
|
@ -0,0 +1,670 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
api_quant.cpp
|
||||
|
||||
Abstract:
|
||||
API for models
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2012-02-29.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include<iostream>
|
||||
#include"z3.h"
|
||||
#include"api_log_macros.h"
|
||||
#include"api_context.h"
|
||||
#include"api_model.h"
|
||||
#include"api_ast_vector.h"
|
||||
#include"array_decl_plugin.h"
|
||||
#include"model.h"
|
||||
#include"model_v2_pp.h"
|
||||
#include"model_smt2_pp.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
void Z3_API Z3_model_inc_ref(Z3_context c, Z3_model m) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_model_inc_ref(c, m);
|
||||
RESET_ERROR_CODE();
|
||||
if (m) {
|
||||
to_model(m)->inc_ref();
|
||||
}
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_model_dec_ref(Z3_context c, Z3_model m) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_model_dec_ref(c, m);
|
||||
RESET_ERROR_CODE();
|
||||
if (m) {
|
||||
to_model(m)->dec_ref();
|
||||
}
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_model_get_const_interp(Z3_context c, Z3_model m, Z3_func_decl a) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_model_get_const_interp(c, m, a);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_NON_NULL(m, 0);
|
||||
expr * r = to_model_ref(m)->get_const_interp(to_func_decl(a));
|
||||
if (!r) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
RETURN_Z3(of_expr(r));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_func_interp Z3_API Z3_model_get_func_interp(Z3_context c, Z3_model m, Z3_func_decl f) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_model_get_func_interp(c, m, f);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_NON_NULL(m, 0);
|
||||
func_interp * _fi = to_model_ref(m)->get_func_interp(to_func_decl(f));
|
||||
if (!_fi) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
Z3_func_interp_ref * fi = alloc(Z3_func_interp_ref, to_model_ref(m));
|
||||
fi->m_func_interp = _fi;
|
||||
mk_c(c)->save_object(fi);
|
||||
RETURN_Z3(of_func_interp(fi));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
unsigned Z3_API Z3_model_get_num_consts(Z3_context c, Z3_model m) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_model_get_num_consts(c, m);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_NON_NULL(m, 0);
|
||||
return to_model_ref(m)->get_num_constants();
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_func_decl Z3_API Z3_model_get_const_decl(Z3_context c, Z3_model m, unsigned i) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_model_get_const_decl(c, m, i);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_NON_NULL(m, 0);
|
||||
model * _m = to_model_ref(m);
|
||||
if (i < _m->get_num_constants()) {
|
||||
RETURN_Z3(of_func_decl(_m->get_constant(i)));
|
||||
}
|
||||
else {
|
||||
SET_ERROR_CODE(Z3_IOB);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
unsigned Z3_API Z3_model_get_num_funcs(Z3_context c, Z3_model m) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_model_get_num_funcs(c, m);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_NON_NULL(m, 0);
|
||||
return to_model_ref(m)->get_num_functions();
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_func_decl get_model_func_decl_core(Z3_context c, Z3_model m, unsigned i) {
|
||||
CHECK_NON_NULL(m, 0);
|
||||
model * _m = to_model_ref(m);
|
||||
if (i >= _m->get_num_functions()) {
|
||||
SET_ERROR_CODE(Z3_IOB);
|
||||
return 0;
|
||||
}
|
||||
return of_func_decl(_m->get_function(i));
|
||||
}
|
||||
|
||||
Z3_func_decl Z3_API Z3_model_get_func_decl(Z3_context c, Z3_model m, unsigned i) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_model_func_decl(c, m, i);
|
||||
RESET_ERROR_CODE();
|
||||
Z3_func_decl r = get_model_func_decl_core(c, m, i);
|
||||
RETURN_Z3(r);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_bool Z3_API Z3_model_eval(Z3_context c, Z3_model m, Z3_ast t, Z3_bool model_completion, Z3_ast * v) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_model_eval(c, m, t, model_completion, v);
|
||||
if (v) *v = 0;
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_NON_NULL(m, Z3_FALSE);
|
||||
model * _m = to_model_ref(m);
|
||||
expr_ref result(mk_c(c)->m());
|
||||
_m->eval(to_expr(t), result, model_completion == Z3_TRUE);
|
||||
mk_c(c)->save_ast_trail(result.get());
|
||||
*v = of_ast(result.get());
|
||||
RETURN_Z3_model_eval Z3_TRUE;
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
unsigned Z3_API Z3_model_get_num_sorts(Z3_context c, Z3_model m) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_model_get_num_sorts(c, m);
|
||||
RESET_ERROR_CODE();
|
||||
return to_model_ref(m)->get_num_uninterpreted_sorts();
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_sort Z3_API Z3_model_get_sort(Z3_context c, Z3_model m, unsigned i) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_model_get_sort(c, m, i);
|
||||
RESET_ERROR_CODE();
|
||||
if (i >= to_model_ref(m)->get_num_uninterpreted_sorts()) {
|
||||
SET_ERROR_CODE(Z3_IOB);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
sort * s = to_model_ref(m)->get_uninterpreted_sort(i);
|
||||
RETURN_Z3(of_sort(s));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast_vector Z3_API Z3_model_get_sort_universe(Z3_context c, Z3_model m, Z3_sort s) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_model_get_sort_universe(c, m, s);
|
||||
RESET_ERROR_CODE();
|
||||
if (!to_model_ref(m)->has_uninterpreted_sort(to_sort(s))) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
ptr_vector<expr> const & universe = to_model_ref(m)->get_universe(to_sort(s));
|
||||
Z3_ast_vector_ref * v = alloc(Z3_ast_vector_ref, mk_c(c)->m());
|
||||
mk_c(c)->save_object(v);
|
||||
unsigned sz = universe.size();
|
||||
for (unsigned i = 0; i < sz; i++) {
|
||||
v->m_ast_vector.push_back(universe[i]);
|
||||
}
|
||||
RETURN_Z3(of_ast_vector(v));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_bool Z3_API Z3_is_as_array(Z3_context c, Z3_ast a) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_is_as_array(c, a);
|
||||
RESET_ERROR_CODE();
|
||||
return is_expr(to_ast(a)) && is_app_of(to_expr(a), mk_c(c)->get_array_fid(), OP_AS_ARRAY);
|
||||
Z3_CATCH_RETURN(Z3_FALSE);
|
||||
}
|
||||
|
||||
Z3_func_decl Z3_API Z3_get_as_array_func_decl(Z3_context c, Z3_ast a) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_as_array_func_decl(c, a);
|
||||
RESET_ERROR_CODE();
|
||||
if (is_expr(to_ast(a)) && is_app_of(to_expr(a), mk_c(c)->get_array_fid(), OP_AS_ARRAY)) {
|
||||
return of_func_decl(to_func_decl(to_app(a)->get_decl()->get_parameter(0).get_ast()));
|
||||
}
|
||||
else {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
void Z3_API Z3_func_interp_inc_ref(Z3_context c, Z3_func_interp f) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_func_interp_inc_ref(c, f);
|
||||
RESET_ERROR_CODE();
|
||||
if (f) {
|
||||
to_func_interp(f)->inc_ref();
|
||||
}
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_func_interp_dec_ref(Z3_context c, Z3_func_interp f) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_func_interp_dec_ref(c, f);
|
||||
RESET_ERROR_CODE();
|
||||
if (f) {
|
||||
to_func_interp(f)->dec_ref();
|
||||
}
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
unsigned Z3_API Z3_func_interp_get_num_entries(Z3_context c, Z3_func_interp f) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_func_interp_get_num_entries(c, f);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_NON_NULL(f, 0);
|
||||
return to_func_interp_ref(f)->num_entries();
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_func_entry Z3_API Z3_func_interp_get_entry(Z3_context c, Z3_func_interp f, unsigned i) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_func_interp_get_entry(c, f, i);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_NON_NULL(f, 0);
|
||||
if (i >= to_func_interp_ref(f)->num_entries()) {
|
||||
SET_ERROR_CODE(Z3_IOB);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
Z3_func_entry_ref * e = alloc(Z3_func_entry_ref, to_func_interp(f)->m_model.get());
|
||||
e->m_func_interp = to_func_interp_ref(f);
|
||||
e->m_func_entry = to_func_interp_ref(f)->get_entry(i);
|
||||
mk_c(c)->save_object(e);
|
||||
RETURN_Z3(of_func_entry(e));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_func_interp_get_else(Z3_context c, Z3_func_interp f) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_func_interp_get_else(c, f);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_NON_NULL(f, 0);
|
||||
expr * e = to_func_interp_ref(f)->get_else();
|
||||
RETURN_Z3(of_expr(e));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
unsigned Z3_API Z3_func_interp_get_arity(Z3_context c, Z3_func_interp f) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_func_interp_get_arity(c, f);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_NON_NULL(f, 0);
|
||||
return to_func_interp_ref(f)->get_arity();
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
void Z3_API Z3_func_entry_inc_ref(Z3_context c, Z3_func_entry e) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_func_entry_inc_ref(c, e);
|
||||
RESET_ERROR_CODE();
|
||||
if (e) {
|
||||
to_func_entry(e)->inc_ref();
|
||||
}
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_func_entry_dec_ref(Z3_context c, Z3_func_entry e) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_func_entry_dec_ref(c, e);
|
||||
RESET_ERROR_CODE();
|
||||
if (e) {
|
||||
to_func_entry(e)->dec_ref();
|
||||
}
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_func_entry_get_value(Z3_context c, Z3_func_entry e) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_func_entry_get_value(c, e);
|
||||
RESET_ERROR_CODE();
|
||||
expr * v = to_func_entry_ref(e)->get_result();
|
||||
RETURN_Z3(of_expr(v));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
unsigned Z3_API Z3_func_entry_get_num_args(Z3_context c, Z3_func_entry e) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_func_entry_get_num_args(c, e);
|
||||
RESET_ERROR_CODE();
|
||||
return to_func_entry(e)->m_func_interp->get_arity();
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_func_entry_get_arg(Z3_context c, Z3_func_entry e, unsigned i) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_func_entry_get_arg(c, e, i);
|
||||
RESET_ERROR_CODE();
|
||||
if (i >= to_func_entry(e)->m_func_interp->get_arity()) {
|
||||
SET_ERROR_CODE(Z3_IOB);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
expr * r = to_func_entry(e)->m_func_entry->get_arg(i);
|
||||
RETURN_Z3(of_expr(r));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
// ----------------------------
|
||||
//
|
||||
// DEPRECATED API
|
||||
//
|
||||
// ----------------------------
|
||||
|
||||
void Z3_API Z3_del_model(Z3_context c, Z3_model m) {
|
||||
Z3_model_dec_ref(c, m);
|
||||
}
|
||||
|
||||
unsigned Z3_API Z3_get_model_num_constants(Z3_context c, Z3_model m) {
|
||||
return Z3_model_get_num_consts(c, m);
|
||||
}
|
||||
|
||||
Z3_func_decl Z3_API Z3_get_model_constant(Z3_context c, Z3_model m, unsigned i) {
|
||||
return Z3_model_get_const_decl(c, m, i);
|
||||
}
|
||||
|
||||
unsigned Z3_API Z3_get_model_num_funcs(Z3_context c, Z3_model m) {
|
||||
return Z3_model_get_num_funcs(c, m);
|
||||
}
|
||||
|
||||
Z3_func_decl Z3_API Z3_get_model_func_decl(Z3_context c, Z3_model m, unsigned i) {
|
||||
return Z3_model_get_func_decl(c, m, i);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_get_model_func_else(Z3_context c, Z3_model m, unsigned i) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_model_func_else(c, m, i);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_NON_NULL(m, 0);
|
||||
Z3_func_decl d = get_model_func_decl_core(c, m, i);
|
||||
if (d) {
|
||||
model * _m = to_model_ref(m);
|
||||
func_interp * g = _m->get_func_interp(to_func_decl(d));
|
||||
if (g) {
|
||||
expr * e = g->get_else();
|
||||
mk_c(c)->save_ast_trail(e);
|
||||
RETURN_Z3(of_ast(e));
|
||||
}
|
||||
SET_ERROR_CODE(Z3_IOB);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
RETURN_Z3(0);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
unsigned get_model_func_num_entries_core(Z3_context c, Z3_model m, unsigned i) {
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_NON_NULL(m, 0);
|
||||
Z3_func_decl d = get_model_func_decl_core(c, m, i);
|
||||
if (d) {
|
||||
model * _m = to_model_ref(m);
|
||||
func_interp * g = _m->get_func_interp(to_func_decl(d));
|
||||
if (g) {
|
||||
return g->num_entries();
|
||||
}
|
||||
SET_ERROR_CODE(Z3_IOB);
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned Z3_API Z3_get_model_func_num_entries(Z3_context c, Z3_model m, unsigned i) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_model_func_num_entries(c, m, i);
|
||||
return get_model_func_num_entries_core(c, m, i);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
unsigned get_model_func_entry_num_args_core(Z3_context c,
|
||||
Z3_model m,
|
||||
unsigned i,
|
||||
unsigned j) {
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_NON_NULL(m, 0);
|
||||
if (j >= get_model_func_num_entries_core(c, m, i)) {
|
||||
SET_ERROR_CODE(Z3_IOB);
|
||||
return 0;
|
||||
}
|
||||
Z3_func_decl d = get_model_func_decl_core(c, m, i);
|
||||
if (d) {
|
||||
model * _m = to_model_ref(m);
|
||||
func_interp * g = _m->get_func_interp(to_func_decl(d));
|
||||
return g->get_arity();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned Z3_API Z3_get_model_func_entry_num_args(Z3_context c,
|
||||
Z3_model m,
|
||||
unsigned i,
|
||||
unsigned j) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_model_func_entry_num_args(c, m, i, j);
|
||||
return get_model_func_entry_num_args_core(c, m, i, j);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_get_model_func_entry_arg(Z3_context c,
|
||||
Z3_model m,
|
||||
unsigned i,
|
||||
unsigned j,
|
||||
unsigned k) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_model_func_entry_arg(c, m, i, j, k);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_NON_NULL(m, 0);
|
||||
if (j >= get_model_func_num_entries_core(c, m, i) || k >= get_model_func_entry_num_args_core(c, m, i, j)) {
|
||||
SET_ERROR_CODE(Z3_IOB);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
Z3_func_decl d = get_model_func_decl_core(c, m, i);
|
||||
if (d) {
|
||||
model * _m = to_model_ref(m);
|
||||
func_interp * g = _m->get_func_interp(to_func_decl(d));
|
||||
if (g && j < g->num_entries()) {
|
||||
func_entry const * e = g->get_entry(j);
|
||||
if (k < g->get_arity()) {
|
||||
expr * a = e->get_arg(k);
|
||||
mk_c(c)->save_ast_trail(a);
|
||||
RETURN_Z3(of_ast(a));
|
||||
}
|
||||
}
|
||||
SET_ERROR_CODE(Z3_IOB);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
RETURN_Z3(0);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_get_model_func_entry_value(Z3_context c,
|
||||
Z3_model m,
|
||||
unsigned i,
|
||||
unsigned j) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_model_func_entry_value(c, m, i, j);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_NON_NULL(m, 0);
|
||||
if (j >= get_model_func_num_entries_core(c, m, i)) {
|
||||
SET_ERROR_CODE(Z3_IOB);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
Z3_func_decl d = get_model_func_decl_core(c, m, i);
|
||||
if (d) {
|
||||
model * _m = to_model_ref(m);
|
||||
func_interp * g = _m->get_func_interp(to_func_decl(d));
|
||||
if (g && j < g->num_entries()) {
|
||||
func_entry const* e = g->get_entry(j);
|
||||
expr* a = e->get_result();
|
||||
mk_c(c)->save_ast_trail(a);
|
||||
RETURN_Z3(of_ast(a));
|
||||
}
|
||||
SET_ERROR_CODE(Z3_IOB);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
RETURN_Z3(0);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_bool Z3_API Z3_eval(Z3_context c,
|
||||
Z3_model m,
|
||||
Z3_ast t,
|
||||
Z3_ast * v) {
|
||||
return Z3_model_eval(c, m, t, mk_c(c)->fparams().m_model_completion, v);
|
||||
}
|
||||
|
||||
Z3_bool Z3_API Z3_eval_func_decl(Z3_context c,
|
||||
Z3_model m,
|
||||
Z3_func_decl decl,
|
||||
Z3_ast* v) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_eval_func_decl(c, m, decl, v);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_NON_NULL(m, Z3_FALSE);
|
||||
ast_manager & mgr = mk_c(c)->m();
|
||||
model * _m = to_model_ref(m);
|
||||
expr_ref result(mgr);
|
||||
if( _m->eval(to_func_decl(decl), result)) {
|
||||
mk_c(c)->save_ast_trail(result.get());
|
||||
*v = of_ast(result.get());
|
||||
RETURN_Z3_eval_func_decl Z3_TRUE;
|
||||
}
|
||||
else {
|
||||
return Z3_FALSE;
|
||||
}
|
||||
Z3_CATCH_RETURN(Z3_FALSE);
|
||||
}
|
||||
|
||||
|
||||
Z3_bool Z3_API Z3_is_array_value(Z3_context c, Z3_model _m, Z3_ast _v, unsigned* size) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_is_array_value(c, _m, _v, size);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_NON_NULL(_v, Z3_FALSE);
|
||||
CHECK_NON_NULL(_m, Z3_FALSE);
|
||||
model * m = to_model_ref(_m);
|
||||
expr * v = to_expr(_v);
|
||||
ast_manager& mgr = mk_c(c)->m();
|
||||
family_id afid = mk_c(c)->get_array_fid();
|
||||
unsigned sz = 0;
|
||||
array_util pl(mgr);
|
||||
if (pl.is_as_array(v)) {
|
||||
func_decl* f = pl.get_as_array_func_decl(to_app(v));
|
||||
func_interp* g = m->get_func_interp(f);
|
||||
sz = g->num_entries();
|
||||
if (sz > 0 && g->get_arity() != 1) {
|
||||
return Z3_FALSE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
while (pl.is_store(v)) {
|
||||
if (to_app(v)->get_num_args() != 3) {
|
||||
return Z3_FALSE;
|
||||
}
|
||||
v = to_app(v)->get_arg(0);
|
||||
++sz;
|
||||
}
|
||||
if (!is_app_of(v, afid, OP_CONST_ARRAY)) {
|
||||
return Z3_FALSE;
|
||||
}
|
||||
}
|
||||
if (size) {
|
||||
*size = sz;
|
||||
}
|
||||
return Z3_TRUE;
|
||||
Z3_CATCH_RETURN(Z3_FALSE);
|
||||
}
|
||||
|
||||
|
||||
void Z3_API Z3_get_array_value(Z3_context c,
|
||||
Z3_model _m,
|
||||
Z3_ast _v,
|
||||
unsigned num_entries,
|
||||
Z3_ast indices[],
|
||||
Z3_ast values[],
|
||||
Z3_ast* else_value) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_array_value(c, _m, _v, num_entries, indices, values, else_value);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_NON_NULL(_m, );
|
||||
model * m = to_model_ref(_m);
|
||||
|
||||
expr* v = to_expr(_v);
|
||||
family_id afid = mk_c(c)->get_array_fid();
|
||||
ast_manager& mgr = mk_c(c)->m();
|
||||
array_util pl(mgr);
|
||||
|
||||
//
|
||||
// note: _v is already reference counted.
|
||||
// saving the trail for the returned values
|
||||
// is redundant.
|
||||
//
|
||||
unsigned sz = 0;
|
||||
if (pl.is_as_array(v)) {
|
||||
func_decl* f = pl.get_as_array_func_decl(to_app(v));
|
||||
func_interp* g = m->get_func_interp(f);
|
||||
sz = g->num_entries();
|
||||
if (g->get_arity() != 1) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
return;
|
||||
}
|
||||
for (unsigned i = 0; i < sz && i < num_entries; ++i) {
|
||||
indices[i] = of_ast(g->get_entry(i)->get_arg(0));
|
||||
values[i] = of_ast(g->get_entry(i)->get_result());
|
||||
}
|
||||
if (else_value) {
|
||||
*else_value = of_ast(g->get_else());
|
||||
}
|
||||
}
|
||||
else {
|
||||
while (sz <= num_entries && is_app_of(v, afid, OP_STORE)) {
|
||||
app* a = to_app(v);
|
||||
if (a->get_num_args() != 3) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
return;
|
||||
}
|
||||
expr* idx = a->get_arg(1);
|
||||
expr* val = a->get_arg(2);
|
||||
indices[sz] = of_ast(idx);
|
||||
values[sz] = of_ast(val);
|
||||
v = to_app(v)->get_arg(0);
|
||||
++sz;
|
||||
}
|
||||
|
||||
if (is_app_of(v, afid, OP_CONST_ARRAY)) {
|
||||
if (else_value) {
|
||||
*else_value = of_ast(to_app(v)->get_arg(0));
|
||||
}
|
||||
}
|
||||
else {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
return;
|
||||
}
|
||||
}
|
||||
RETURN_Z3_get_array_value;
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
Z3_bool Z3_API Z3_eval_decl(Z3_context c,
|
||||
Z3_model m,
|
||||
Z3_func_decl d,
|
||||
unsigned num_args,
|
||||
Z3_ast const args[],
|
||||
Z3_ast* v) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_eval_decl(c, m, d, num_args, args, v);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_NON_NULL(m, Z3_FALSE);
|
||||
ast_manager & mgr = mk_c(c)->m();
|
||||
model * _m = to_model_ref(m);
|
||||
app_ref app(mgr);
|
||||
app = mgr.mk_app(to_func_decl(d), num_args, to_exprs(args));
|
||||
expr_ref result(mgr);
|
||||
_m->eval(app.get(), result);
|
||||
mk_c(c)->save_ast_trail(result.get());
|
||||
*v = of_ast(result.get());
|
||||
RETURN_Z3_eval_decl Z3_TRUE;
|
||||
Z3_CATCH_RETURN(Z3_FALSE);
|
||||
}
|
||||
|
||||
char const * Z3_API Z3_model_to_string(Z3_context c, Z3_model m) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_model_to_string(c, m);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_NON_NULL(m, 0);
|
||||
std::ostringstream buffer;
|
||||
std::string result;
|
||||
if (mk_c(c)->get_print_mode() == Z3_PRINT_SMTLIB2_COMPLIANT) {
|
||||
model_smt2_pp(buffer, mk_c(c)->m(), *(to_model_ref(m)), 0);
|
||||
// Hack for removing the trailing '\n'
|
||||
result = buffer.str();
|
||||
if (result.size() != 0)
|
||||
result.resize(result.size()-1);
|
||||
}
|
||||
else {
|
||||
model_v2_pp(buffer, *(to_model_ref(m)), mk_c(c)->fparams().m_model_partial);
|
||||
result = buffer.str();
|
||||
}
|
||||
return mk_c(c)->mk_external_string(result);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
};
|
58
lib/api_model.h
Normal file
58
lib/api_model.h
Normal file
|
@ -0,0 +1,58 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
api_model.h
|
||||
|
||||
Abstract:
|
||||
API for models
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2012-03-08.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _API_MODEL_H_
|
||||
#define _API_MODEL_H_
|
||||
|
||||
#include"api_util.h"
|
||||
#include"model.h"
|
||||
|
||||
struct Z3_model_ref : public api::object {
|
||||
model_ref m_model;
|
||||
Z3_model_ref() {}
|
||||
virtual ~Z3_model_ref() {}
|
||||
};
|
||||
|
||||
inline Z3_model_ref * to_model(Z3_model s) { return reinterpret_cast<Z3_model_ref *>(s); }
|
||||
inline Z3_model of_model(Z3_model_ref * s) { return reinterpret_cast<Z3_model>(s); }
|
||||
inline model * to_model_ref(Z3_model s) { return to_model(s)->m_model.get(); }
|
||||
|
||||
struct Z3_func_interp_ref : public api::object {
|
||||
model_ref m_model; // must have it to prevent reference to m_func_interp to be killed.
|
||||
func_interp * m_func_interp;
|
||||
Z3_func_interp_ref(model * m):m_model(m), m_func_interp(0) {}
|
||||
virtual ~Z3_func_interp_ref() {}
|
||||
};
|
||||
|
||||
inline Z3_func_interp_ref * to_func_interp(Z3_func_interp s) { return reinterpret_cast<Z3_func_interp_ref *>(s); }
|
||||
inline Z3_func_interp of_func_interp(Z3_func_interp_ref * s) { return reinterpret_cast<Z3_func_interp>(s); }
|
||||
inline func_interp * to_func_interp_ref(Z3_func_interp s) { return to_func_interp(s)->m_func_interp; }
|
||||
|
||||
struct Z3_func_entry_ref : public api::object {
|
||||
model_ref m_model; // must have it to prevent reference to m_func_entry to be killed.
|
||||
func_interp * m_func_interp;
|
||||
func_entry const * m_func_entry;
|
||||
Z3_func_entry_ref(model * m):m_model(m), m_func_interp(0), m_func_entry(0) {}
|
||||
virtual ~Z3_func_entry_ref() {}
|
||||
};
|
||||
|
||||
inline Z3_func_entry_ref * to_func_entry(Z3_func_entry s) { return reinterpret_cast<Z3_func_entry_ref *>(s); }
|
||||
inline Z3_func_entry of_func_entry(Z3_func_entry_ref * s) { return reinterpret_cast<Z3_func_entry>(s); }
|
||||
inline func_entry const * to_func_entry_ref(Z3_func_entry s) { return to_func_entry(s)->m_func_entry; }
|
||||
|
||||
|
||||
#endif
|
340
lib/api_numeral.cpp
Normal file
340
lib/api_numeral.cpp
Normal file
|
@ -0,0 +1,340 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
api_numeral.cpp
|
||||
|
||||
Abstract:
|
||||
API for handling numerals in Z3
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2012-02-29.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include<iostream>
|
||||
#include"z3.h"
|
||||
#include"api_log_macros.h"
|
||||
#include"api_context.h"
|
||||
#include"api_util.h"
|
||||
#include"arith_decl_plugin.h"
|
||||
#include"bv_decl_plugin.h"
|
||||
#include"algebraic_numbers.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
bool is_numeral_sort(Z3_context c, Z3_sort ty) {
|
||||
sort * _ty = to_sort(ty);
|
||||
family_id fid = _ty->get_family_id();
|
||||
if (fid != mk_c(c)->get_arith_fid() &&
|
||||
fid != mk_c(c)->get_bv_fid() &&
|
||||
fid != mk_c(c)->get_datalog_fid()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool check_numeral_sort(Z3_context c, Z3_sort ty) {
|
||||
bool is_num = is_numeral_sort(c, ty);
|
||||
if (!is_num) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
}
|
||||
return is_num;
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_mk_numeral(Z3_context c, const char* n, Z3_sort ty) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_numeral(c, n, ty);
|
||||
RESET_ERROR_CODE();
|
||||
if (!check_numeral_sort(c, ty)) {
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
if (!n) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
std::string fixed_num;
|
||||
char const* m = n;
|
||||
while (*m) {
|
||||
if (!(('0' <= *m && *m <= '9') ||
|
||||
('/' == *m) || ('-' == *m) ||
|
||||
(' ' == *m) || ('\n' == *m) ||
|
||||
('.' == *m) || ('e' == *m) ||
|
||||
('E' == *m))) {
|
||||
SET_ERROR_CODE(Z3_PARSER_ERROR);
|
||||
return 0;
|
||||
}
|
||||
++m;
|
||||
}
|
||||
ast * a = mk_c(c)->mk_numeral_core(rational(n), to_sort(ty));
|
||||
RETURN_Z3(of_ast(a));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_mk_int(Z3_context c, int value, Z3_sort ty) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_int(c, value, ty);
|
||||
RESET_ERROR_CODE();
|
||||
if (!check_numeral_sort(c, ty)) {
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
ast * a = mk_c(c)->mk_numeral_core(rational(value), to_sort(ty));
|
||||
RETURN_Z3(of_ast(a));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_mk_unsigned_int(Z3_context c, unsigned value, Z3_sort ty) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_unsigned_int(c, value, ty);
|
||||
RESET_ERROR_CODE();
|
||||
if (!check_numeral_sort(c, ty)) {
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
ast * a = mk_c(c)->mk_numeral_core(rational(value), to_sort(ty));
|
||||
RETURN_Z3(of_ast(a));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_mk_int64(Z3_context c, long long value, Z3_sort ty) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_int64(c, value, ty);
|
||||
RESET_ERROR_CODE();
|
||||
if (!check_numeral_sort(c, ty)) {
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
rational n(value, rational::i64());
|
||||
ast* a = mk_c(c)->mk_numeral_core(n, to_sort(ty));
|
||||
RETURN_Z3(of_ast(a));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_mk_unsigned_int64(Z3_context c, unsigned long long value, Z3_sort ty) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_unsigned_int64(c, value, ty);
|
||||
RESET_ERROR_CODE();
|
||||
if (!check_numeral_sort(c, ty)) {
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
rational n(value, rational::ui64());
|
||||
ast * a = mk_c(c)->mk_numeral_core(n, to_sort(ty));
|
||||
RETURN_Z3(of_ast(a));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_bool Z3_API Z3_is_numeral_ast(Z3_context c, Z3_ast a) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_is_numeral_ast(c, a);
|
||||
RESET_ERROR_CODE();
|
||||
expr* e = to_expr(a);
|
||||
return
|
||||
mk_c(c)->autil().is_numeral(e) ||
|
||||
mk_c(c)->bvutil().is_numeral(e);
|
||||
Z3_CATCH_RETURN(Z3_FALSE);
|
||||
}
|
||||
|
||||
Z3_bool Z3_API Z3_get_numeral_rational(Z3_context c, Z3_ast a, rational& r) {
|
||||
Z3_TRY;
|
||||
// This function is not part of the public API
|
||||
RESET_ERROR_CODE();
|
||||
expr* e = to_expr(a);
|
||||
if (!e) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
return Z3_FALSE;
|
||||
}
|
||||
if (mk_c(c)->autil().is_numeral(e, r)) {
|
||||
return Z3_TRUE;
|
||||
}
|
||||
unsigned bv_size;
|
||||
if (mk_c(c)->bvutil().is_numeral(e, r, bv_size)) {
|
||||
return Z3_TRUE;
|
||||
}
|
||||
uint64 v;
|
||||
if (mk_c(c)->datalog_util().is_numeral(e, v)) {
|
||||
r = rational(v, rational::ui64());
|
||||
return Z3_TRUE;
|
||||
}
|
||||
return Z3_FALSE;
|
||||
Z3_CATCH_RETURN(Z3_FALSE);
|
||||
}
|
||||
|
||||
|
||||
Z3_string Z3_API Z3_get_numeral_string(Z3_context c, Z3_ast a) {
|
||||
Z3_TRY;
|
||||
// This function invokes Z3_get_numeral_rational, but it is still ok to add LOG command here because it does not return a Z3 object.
|
||||
LOG_Z3_get_numeral_string(c, a);
|
||||
RESET_ERROR_CODE();
|
||||
rational r;
|
||||
Z3_bool ok = Z3_get_numeral_rational(c, a, r);
|
||||
if (ok == Z3_TRUE) {
|
||||
return mk_c(c)->mk_external_string(r.to_string());
|
||||
}
|
||||
else {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
return "";
|
||||
}
|
||||
Z3_CATCH_RETURN("");
|
||||
}
|
||||
|
||||
Z3_string Z3_API Z3_get_numeral_decimal_string(Z3_context c, Z3_ast a, unsigned precision) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_numeral_decimal_string(c, a, precision);
|
||||
RESET_ERROR_CODE();
|
||||
expr* e = to_expr(a);
|
||||
if (!e) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
return "";
|
||||
}
|
||||
rational r;
|
||||
arith_util & u = mk_c(c)->autil();
|
||||
if (u.is_numeral(e, r) && !r.is_int()) {
|
||||
std::ostringstream buffer;
|
||||
r.display_decimal(buffer, precision);
|
||||
return mk_c(c)->mk_external_string(buffer.str());
|
||||
}
|
||||
if (u.is_irrational_algebraic_numeral(e)) {
|
||||
algebraic_numbers::anum const & n = u.to_irrational_algebraic_numeral(e);
|
||||
algebraic_numbers::manager & am = u.am();
|
||||
std::ostringstream buffer;
|
||||
am.display_decimal(buffer, n, precision);
|
||||
return mk_c(c)->mk_external_string(buffer.str());
|
||||
}
|
||||
Z3_bool ok = Z3_get_numeral_rational(c, a, r);
|
||||
if (ok == Z3_TRUE) {
|
||||
return mk_c(c)->mk_external_string(r.to_string());
|
||||
}
|
||||
else {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
return "";
|
||||
}
|
||||
Z3_CATCH_RETURN("");
|
||||
}
|
||||
|
||||
Z3_bool Z3_API Z3_get_numeral_small(Z3_context c, Z3_ast a, long long* num, long long* den) {
|
||||
Z3_TRY;
|
||||
// This function invokes Z3_get_numeral_rational, but it is still ok to add LOG command here because it does not return a Z3 object.
|
||||
LOG_Z3_get_numeral_small(c, a, num, den);
|
||||
RESET_ERROR_CODE();
|
||||
rational r;
|
||||
Z3_bool ok = Z3_get_numeral_rational(c, a, r);
|
||||
if (ok == Z3_TRUE) {
|
||||
rational n = numerator(r);
|
||||
rational d = denominator(r);
|
||||
if (n.is_int64() && d.is_int64()) {
|
||||
*num = n.get_int64();
|
||||
*den = d.get_int64();
|
||||
return Z3_TRUE;
|
||||
}
|
||||
else {
|
||||
return Z3_FALSE;
|
||||
}
|
||||
}
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
return Z3_FALSE;
|
||||
Z3_CATCH_RETURN(Z3_FALSE);
|
||||
}
|
||||
|
||||
|
||||
Z3_bool Z3_API Z3_get_numeral_int(Z3_context c, Z3_ast v, int* i) {
|
||||
Z3_TRY;
|
||||
// This function invokes Z3_get_numeral_int64, but it is still ok to add LOG command here because it does not return a Z3 object.
|
||||
LOG_Z3_get_numeral_int(c, v, i);
|
||||
RESET_ERROR_CODE();
|
||||
if (!i) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
return Z3_FALSE;
|
||||
}
|
||||
long long l;
|
||||
if (Z3_get_numeral_int64(c, v, &l) && l >= INT_MIN && l <= INT_MAX) {
|
||||
*i = static_cast<int>(l);
|
||||
return Z3_TRUE;
|
||||
}
|
||||
return Z3_FALSE;
|
||||
Z3_CATCH_RETURN(Z3_FALSE);
|
||||
}
|
||||
|
||||
Z3_bool Z3_API Z3_get_numeral_uint(Z3_context c, Z3_ast v, unsigned* u) {
|
||||
Z3_TRY;
|
||||
// This function invokes Z3_get_numeral_uint64, but it is still ok to add LOG command here because it does not return a Z3 object.
|
||||
LOG_Z3_get_numeral_uint(c, v, u);
|
||||
RESET_ERROR_CODE();
|
||||
if (!u) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
return Z3_FALSE;
|
||||
}
|
||||
unsigned long long l;
|
||||
if (Z3_get_numeral_uint64(c, v, &l) && (l <= 0xFFFFFFFF)) {
|
||||
*u = static_cast<unsigned>(l);
|
||||
return Z3_TRUE;
|
||||
}
|
||||
return Z3_FALSE;
|
||||
Z3_CATCH_RETURN(Z3_FALSE);
|
||||
}
|
||||
|
||||
Z3_bool Z3_API Z3_get_numeral_uint64(Z3_context c, Z3_ast v, unsigned long long* u) {
|
||||
Z3_TRY;
|
||||
// This function invokes Z3_get_numeral_rational, but it is still ok to add LOG command here because it does not return a Z3 object.
|
||||
LOG_Z3_get_numeral_uint64(c, v, u);
|
||||
RESET_ERROR_CODE();
|
||||
if (!u) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
return Z3_FALSE;
|
||||
}
|
||||
rational r;
|
||||
Z3_bool ok = Z3_get_numeral_rational(c, v, r);
|
||||
SASSERT(u);
|
||||
if (ok == Z3_TRUE && r.is_uint64()) {
|
||||
*u = r.get_uint64();
|
||||
return ok;
|
||||
}
|
||||
return Z3_FALSE;
|
||||
Z3_CATCH_RETURN(Z3_FALSE);
|
||||
}
|
||||
|
||||
Z3_bool Z3_API Z3_get_numeral_int64(Z3_context c, Z3_ast v, long long* i) {
|
||||
Z3_TRY;
|
||||
// This function invokes Z3_get_numeral_rational, but it is still ok to add LOG command here because it does not return a Z3 object.
|
||||
LOG_Z3_get_numeral_int64(c, v, i);
|
||||
RESET_ERROR_CODE();
|
||||
if (!i) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
return Z3_FALSE;
|
||||
}
|
||||
rational r;
|
||||
Z3_bool ok = Z3_get_numeral_rational(c, v, r);
|
||||
if (ok == Z3_TRUE && r.is_int64()) {
|
||||
*i = r.get_int64();
|
||||
return ok;
|
||||
}
|
||||
return Z3_FALSE;
|
||||
Z3_CATCH_RETURN(Z3_FALSE);
|
||||
}
|
||||
|
||||
Z3_bool Z3_API Z3_get_numeral_rational_int64(Z3_context c, Z3_ast v, long long* num, long long* den) {
|
||||
Z3_TRY;
|
||||
// This function invokes Z3_get_numeral_rational, but it is still ok to add LOG command here because it does not return a Z3 object.
|
||||
LOG_Z3_get_numeral_rational_int64(c, v, num, den);
|
||||
RESET_ERROR_CODE();
|
||||
if (!num || !den) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
return Z3_FALSE;
|
||||
}
|
||||
rational r;
|
||||
Z3_bool ok = Z3_get_numeral_rational(c, v, r);
|
||||
if (ok != Z3_TRUE) {
|
||||
return ok;
|
||||
}
|
||||
rational n = numerator(r);
|
||||
rational d = denominator(r);
|
||||
if (n.is_int64() && d.is_int64()) {
|
||||
*num = n.get_int64();
|
||||
*den = d.get_int64();
|
||||
return ok;
|
||||
}
|
||||
return Z3_FALSE;
|
||||
Z3_CATCH_RETURN(Z3_FALSE);
|
||||
}
|
||||
|
||||
};
|
182
lib/api_params.cpp
Normal file
182
lib/api_params.cpp
Normal file
|
@ -0,0 +1,182 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
api_params.cpp
|
||||
|
||||
Abstract:
|
||||
API for creating parameter sets.
|
||||
|
||||
This is essentially a wrapper for params_ref.
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2012-03-05.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include<iostream>
|
||||
#include"z3.h"
|
||||
#include"api_log_macros.h"
|
||||
#include"api_context.h"
|
||||
#include"api_util.h"
|
||||
#include"params.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
Z3_params Z3_API Z3_mk_params(Z3_context c) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_params(c);
|
||||
RESET_ERROR_CODE();
|
||||
Z3_params_ref * p = alloc(Z3_params_ref);
|
||||
mk_c(c)->save_object(p);
|
||||
Z3_params r = of_params(p);
|
||||
RETURN_Z3(r);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Increment the reference counter of the given parameter set.
|
||||
*/
|
||||
void Z3_API Z3_params_inc_ref(Z3_context c, Z3_params p) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_params_inc_ref(c, p);
|
||||
RESET_ERROR_CODE();
|
||||
to_params(p)->inc_ref();
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Decrement the reference counter of the given parameter set.
|
||||
*/
|
||||
void Z3_API Z3_params_dec_ref(Z3_context c, Z3_params p) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_params_dec_ref(c, p);
|
||||
RESET_ERROR_CODE();
|
||||
to_params(p)->dec_ref();
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Add a Boolean parameter \c k with value \c v to the parameter set \c p.
|
||||
*/
|
||||
void Z3_API Z3_params_set_bool(Z3_context c, Z3_params p, Z3_symbol k, Z3_bool v) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_params_set_bool(c, p, k, v);
|
||||
RESET_ERROR_CODE();
|
||||
to_params(p)->m_params.set_bool(to_symbol(k), v != 0);
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Add a unsigned parameter \c k with value \c v to the parameter set \c p.
|
||||
*/
|
||||
void Z3_API Z3_params_set_uint(Z3_context c, Z3_params p, Z3_symbol k, unsigned v) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_params_set_uint(c, p, k, v);
|
||||
RESET_ERROR_CODE();
|
||||
to_params(p)->m_params.set_uint(to_symbol(k), v);
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Add a double parameter \c k with value \c v to the parameter set \c p.
|
||||
*/
|
||||
void Z3_API Z3_params_set_double(Z3_context c, Z3_params p, Z3_symbol k, double v) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_params_set_double(c, p, k, v);
|
||||
RESET_ERROR_CODE();
|
||||
to_params(p)->m_params.set_double(to_symbol(k), v);
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Add a symbol parameter \c k with value \c v to the parameter set \c p.
|
||||
*/
|
||||
void Z3_API Z3_params_set_symbol(Z3_context c, Z3_params p, Z3_symbol k, Z3_symbol v) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_params_set_symbol(c, p, k, v);
|
||||
RESET_ERROR_CODE();
|
||||
to_params(p)->m_params.set_sym(to_symbol(k), to_symbol(v));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Convert a parameter set into a string. This function is mainly used for printing the
|
||||
contents of a parameter set.
|
||||
*/
|
||||
Z3_string Z3_API Z3_params_to_string(Z3_context c, Z3_params p) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_params_to_string(c, p);
|
||||
RESET_ERROR_CODE();
|
||||
std::ostringstream buffer;
|
||||
to_params(p)->m_params.display(buffer);
|
||||
return mk_c(c)->mk_external_string(buffer.str());
|
||||
Z3_CATCH_RETURN("");
|
||||
}
|
||||
|
||||
void Z3_API Z3_params_validate(Z3_context c, Z3_params p, Z3_param_descrs d) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_params_validate(c, p, d);
|
||||
RESET_ERROR_CODE();
|
||||
to_params(p)->m_params.validate(*to_param_descrs_ptr(d));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_param_descrs_inc_ref(Z3_context c, Z3_param_descrs p) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_param_descrs_inc_ref(c, p);
|
||||
RESET_ERROR_CODE();
|
||||
to_param_descrs(p)->inc_ref();
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_param_descrs_dec_ref(Z3_context c, Z3_param_descrs p) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_param_descrs_dec_ref(c, p);
|
||||
RESET_ERROR_CODE();
|
||||
to_param_descrs(p)->dec_ref();
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
Z3_param_kind Z3_API Z3_param_descrs_get_kind(Z3_context c, Z3_param_descrs p, Z3_symbol n) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_param_descrs_get_kind(c, p, n);
|
||||
RESET_ERROR_CODE();
|
||||
param_kind k = to_param_descrs_ptr(p)->get_kind(to_symbol(n));
|
||||
switch (k) {
|
||||
case CPK_UINT: return Z3_PK_UINT;
|
||||
case CPK_BOOL: return Z3_PK_BOOL;
|
||||
case CPK_DOUBLE: return Z3_PK_DOUBLE;
|
||||
case CPK_STRING: return Z3_PK_STRING;
|
||||
case CPK_SYMBOL: return Z3_PK_SYMBOL;
|
||||
case CPK_INVALID: return Z3_PK_INVALID;
|
||||
default: return Z3_PK_OTHER;
|
||||
}
|
||||
Z3_CATCH_RETURN(Z3_PK_INVALID);
|
||||
}
|
||||
|
||||
unsigned Z3_API Z3_param_descrs_size(Z3_context c, Z3_param_descrs p) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_param_descrs_size(c, p);
|
||||
RESET_ERROR_CODE();
|
||||
return to_param_descrs_ptr(p)->size();
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_symbol Z3_API Z3_param_descrs_get_name(Z3_context c, Z3_param_descrs p, unsigned i) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_param_descrs_get_name(c, p, i);
|
||||
RESET_ERROR_CODE();
|
||||
if (i >= to_param_descrs_ptr(p)->size()) {
|
||||
SET_ERROR_CODE(Z3_IOB);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
Z3_symbol result = of_symbol(to_param_descrs_ptr(p)->get_param_name(i));
|
||||
return result;
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
};
|
426
lib/api_parsers.cpp
Normal file
426
lib/api_parsers.cpp
Normal file
|
@ -0,0 +1,426 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
api_parsers.cpp
|
||||
|
||||
Abstract:
|
||||
API for parsing different formats
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2012-02-29.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include<iostream>
|
||||
#include"z3.h"
|
||||
#include"api_log_macros.h"
|
||||
#include"api_context.h"
|
||||
#include"api_util.h"
|
||||
#include"cmd_context.h"
|
||||
#include"smt2parser.h"
|
||||
#include"smtparser.h"
|
||||
#include"z3_solver.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
void init_smtlib_parser(Z3_context c,
|
||||
unsigned num_sorts,
|
||||
Z3_symbol const sort_names[],
|
||||
Z3_sort const types[],
|
||||
unsigned num_decls,
|
||||
Z3_symbol const decl_names[],
|
||||
Z3_func_decl const decls[]) {
|
||||
mk_c(c)->reset_parser();
|
||||
mk_c(c)->m_smtlib_parser = smtlib::parser::create(mk_c(c)->m());
|
||||
mk_c(c)->m_smtlib_parser->initialize_smtlib();
|
||||
smtlib::symtable * table = mk_c(c)->m_smtlib_parser->get_benchmark()->get_symtable();
|
||||
for (unsigned i = 0; i < num_sorts; i++) {
|
||||
table->insert(to_symbol(sort_names[i]), to_sort(types[i]));
|
||||
}
|
||||
for (unsigned i = 0; i < num_decls; i++) {
|
||||
table->insert(to_symbol(decl_names[i]), to_func_decl(decls[i]));
|
||||
}
|
||||
}
|
||||
|
||||
void Z3_API Z3_parse_smtlib_string(Z3_context c,
|
||||
const char * str,
|
||||
unsigned num_sorts,
|
||||
Z3_symbol const sort_names[],
|
||||
Z3_sort const sorts[],
|
||||
unsigned num_decls,
|
||||
Z3_symbol const decl_names[],
|
||||
Z3_func_decl const decls[]) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_parse_smtlib_string(c, str, num_sorts, sort_names, sorts, num_decls, decl_names, decls);
|
||||
std::ostringstream outs;
|
||||
bool ok = false;
|
||||
|
||||
RESET_ERROR_CODE();
|
||||
init_smtlib_parser(c, num_sorts, sort_names, sorts, num_decls, decl_names, decls);
|
||||
mk_c(c)->m_smtlib_parser->set_error_stream(outs);
|
||||
try {
|
||||
ok = mk_c(c)->m_smtlib_parser->parse_string(str);
|
||||
}
|
||||
catch (...) {
|
||||
ok = false;
|
||||
}
|
||||
mk_c(c)->m_smtlib_error_buffer = outs.str();
|
||||
if (!ok) {
|
||||
mk_c(c)->reset_parser();
|
||||
SET_ERROR_CODE(Z3_PARSER_ERROR);
|
||||
}
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_parse_smtlib_file(Z3_context c,
|
||||
const char * file_name,
|
||||
unsigned num_sorts,
|
||||
Z3_symbol const sort_names[],
|
||||
Z3_sort const types[],
|
||||
unsigned num_decls,
|
||||
Z3_symbol const decl_names[],
|
||||
Z3_func_decl const decls[]) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_parse_smtlib_file(c, file_name, num_sorts, sort_names, types, num_decls, decl_names, decls);
|
||||
bool ok = false;
|
||||
RESET_ERROR_CODE();
|
||||
std::ostringstream outs;
|
||||
init_smtlib_parser(c, num_sorts, sort_names, types, num_decls, decl_names, decls);
|
||||
mk_c(c)->m_smtlib_parser->set_error_stream(outs);
|
||||
try {
|
||||
ok = mk_c(c)->m_smtlib_parser->parse_file(file_name);
|
||||
}
|
||||
catch(...) {
|
||||
ok = false;
|
||||
}
|
||||
mk_c(c)->m_smtlib_error_buffer = outs.str();
|
||||
if (!ok) {
|
||||
mk_c(c)->reset_parser();
|
||||
SET_ERROR_CODE(Z3_PARSER_ERROR);
|
||||
}
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
unsigned Z3_API Z3_get_smtlib_num_formulas(Z3_context c) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_smtlib_num_formulas(c);
|
||||
RESET_ERROR_CODE();
|
||||
if (mk_c(c)->m_smtlib_parser) {
|
||||
return mk_c(c)->m_smtlib_parser->get_benchmark()->get_num_formulas();
|
||||
}
|
||||
SET_ERROR_CODE(Z3_NO_PARSER);
|
||||
return 0;
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_get_smtlib_formula(Z3_context c, unsigned i) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_smtlib_formula(c, i);
|
||||
RESET_ERROR_CODE();
|
||||
if (mk_c(c)->m_smtlib_parser) {
|
||||
if (i < mk_c(c)->m_smtlib_parser->get_benchmark()->get_num_formulas()) {
|
||||
ast * f = mk_c(c)->m_smtlib_parser->get_benchmark()->begin_formulas()[i];
|
||||
mk_c(c)->save_ast_trail(f);
|
||||
RETURN_Z3(of_ast(f));
|
||||
}
|
||||
else {
|
||||
SET_ERROR_CODE(Z3_IOB);
|
||||
}
|
||||
}
|
||||
else {
|
||||
SET_ERROR_CODE(Z3_NO_PARSER);
|
||||
}
|
||||
RETURN_Z3(0);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
unsigned Z3_API Z3_get_smtlib_num_assumptions(Z3_context c) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_smtlib_num_assumptions(c);
|
||||
RESET_ERROR_CODE();
|
||||
if (mk_c(c)->m_smtlib_parser) {
|
||||
return mk_c(c)->m_smtlib_parser->get_benchmark()->get_num_axioms();
|
||||
}
|
||||
SET_ERROR_CODE(Z3_NO_PARSER);
|
||||
return 0;
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_get_smtlib_assumption(Z3_context c, unsigned i) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_smtlib_assumption(c, i);
|
||||
RESET_ERROR_CODE();
|
||||
if (mk_c(c)->m_smtlib_parser) {
|
||||
if (i < mk_c(c)->m_smtlib_parser->get_benchmark()->get_num_axioms()) {
|
||||
ast * a = mk_c(c)->m_smtlib_parser->get_benchmark()->begin_axioms()[i];
|
||||
mk_c(c)->save_ast_trail(a);
|
||||
RETURN_Z3(of_ast(a));
|
||||
}
|
||||
else {
|
||||
SET_ERROR_CODE(Z3_IOB);
|
||||
}
|
||||
}
|
||||
else {
|
||||
SET_ERROR_CODE(Z3_NO_PARSER);
|
||||
}
|
||||
RETURN_Z3(0);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
unsigned Z3_API Z3_get_smtlib_num_decls(Z3_context c) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_smtlib_num_decls(c);
|
||||
RESET_ERROR_CODE();
|
||||
if (mk_c(c)->m_smtlib_parser) {
|
||||
mk_c(c)->extract_smtlib_parser_decls();
|
||||
return mk_c(c)->m_smtlib_parser_decls.size();
|
||||
}
|
||||
SET_ERROR_CODE(Z3_NO_PARSER);
|
||||
return 0;
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_func_decl Z3_API Z3_get_smtlib_decl(Z3_context c, unsigned i) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_smtlib_decl(c, i);
|
||||
RESET_ERROR_CODE();
|
||||
mk_c(c)->extract_smtlib_parser_decls();
|
||||
if (mk_c(c)->m_smtlib_parser) {
|
||||
if (i < mk_c(c)->m_smtlib_parser_decls.size()) {
|
||||
func_decl * d = mk_c(c)->m_smtlib_parser_decls[i];
|
||||
mk_c(c)->save_ast_trail(d);
|
||||
RETURN_Z3(of_func_decl(d));
|
||||
}
|
||||
else {
|
||||
SET_ERROR_CODE(Z3_IOB);
|
||||
}
|
||||
}
|
||||
else {
|
||||
SET_ERROR_CODE(Z3_NO_PARSER);
|
||||
}
|
||||
RETURN_Z3(0);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
unsigned Z3_API Z3_get_smtlib_num_sorts(Z3_context c) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_smtlib_num_sorts(c);
|
||||
RESET_ERROR_CODE();
|
||||
if (mk_c(c)->m_smtlib_parser) {
|
||||
mk_c(c)->extract_smtlib_parser_decls();
|
||||
return mk_c(c)->m_smtlib_parser_sorts.size();
|
||||
}
|
||||
SET_ERROR_CODE(Z3_NO_PARSER);
|
||||
return 0;
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_sort Z3_API Z3_get_smtlib_sort(Z3_context c, unsigned i) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_smtlib_sort(c, i);
|
||||
RESET_ERROR_CODE();
|
||||
if (mk_c(c)->m_smtlib_parser) {
|
||||
mk_c(c)->extract_smtlib_parser_decls();
|
||||
if (i < mk_c(c)->m_smtlib_parser_sorts.size()) {
|
||||
sort* s = mk_c(c)->m_smtlib_parser_sorts[i];
|
||||
mk_c(c)->save_ast_trail(s);
|
||||
RETURN_Z3(of_sort(s));
|
||||
}
|
||||
else {
|
||||
SET_ERROR_CODE(Z3_IOB);
|
||||
}
|
||||
}
|
||||
else {
|
||||
SET_ERROR_CODE(Z3_NO_PARSER);
|
||||
}
|
||||
RETURN_Z3(0);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_string Z3_API Z3_get_smtlib_error(Z3_context c) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_smtlib_error(c);
|
||||
RESET_ERROR_CODE();
|
||||
return mk_c(c)->m_smtlib_error_buffer.c_str();
|
||||
Z3_CATCH_RETURN("");
|
||||
}
|
||||
|
||||
Z3_ast parse_z3_stream(Z3_context c, std::istream& is) {
|
||||
z3_solver parser(c, is, verbose_stream(), mk_c(c)->fparams(), false);
|
||||
if (!parser.parse()) {
|
||||
SET_ERROR_CODE(Z3_PARSER_ERROR);
|
||||
return of_ast(mk_c(c)->m().mk_true());
|
||||
}
|
||||
expr_ref_vector assumptions(mk_c(c)->m());
|
||||
parser.get_assumptions(assumptions);
|
||||
return of_ast(mk_c(c)->mk_and(assumptions.size(), assumptions.c_ptr()));
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_parse_z3_string(Z3_context c, Z3_string str) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_parse_z3_string(c, str);
|
||||
std::string s(str);
|
||||
std::istringstream is(s);
|
||||
Z3_ast r = parse_z3_stream(c, is);
|
||||
RETURN_Z3(r);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_parse_z3_file(Z3_context c, Z3_string file_name) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_parse_z3_file(c, file_name);
|
||||
std::ifstream is(file_name);
|
||||
if (!is) {
|
||||
SET_ERROR_CODE(Z3_PARSER_ERROR);
|
||||
return 0;
|
||||
}
|
||||
Z3_ast r = parse_z3_stream(c, is);
|
||||
RETURN_Z3(r);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
// ---------------
|
||||
// Support for SMTLIB2
|
||||
|
||||
class z3_context_solver : public solver {
|
||||
api::context & m_ctx;
|
||||
smt::solver & ctx() const { return m_ctx.get_solver(); }
|
||||
public:
|
||||
virtual ~z3_context_solver() {}
|
||||
z3_context_solver(api::context& c) : m_ctx(c) {}
|
||||
virtual void init(ast_manager & m, symbol const & logic) {}
|
||||
virtual void collect_statistics(statistics & st) const {}
|
||||
virtual void reset() { ctx().reset(); }
|
||||
virtual void assert_expr(expr * t) { ctx().assert_expr(t); }
|
||||
virtual void push() { ctx().push(); }
|
||||
virtual void pop(unsigned n) { ctx().pop(n); }
|
||||
virtual unsigned get_scope_level() const { return ctx().get_scope_level(); }
|
||||
virtual lbool check_sat(unsigned num_assumptions, expr * const * assumptions) {
|
||||
return ctx().check(num_assumptions, assumptions);
|
||||
}
|
||||
virtual void get_unsat_core(ptr_vector<expr> & r) {
|
||||
unsigned sz = ctx().get_unsat_core_size();
|
||||
for (unsigned i = 0; i < sz; i++)
|
||||
r.push_back(ctx().get_unsat_core_expr(i));
|
||||
}
|
||||
virtual void get_model(model_ref & m) { ctx().get_model(m); }
|
||||
virtual proof * get_proof() { return ctx().get_proof(); }
|
||||
virtual std::string reason_unknown() const { return ctx().last_failure_as_string(); }
|
||||
virtual void get_labels(svector<symbol> & r) {
|
||||
buffer<symbol> tmp;
|
||||
ctx().get_relevant_labels(0, tmp);
|
||||
r.append(tmp.size(), tmp.c_ptr());
|
||||
}
|
||||
|
||||
// These are controlled by the main API
|
||||
virtual void set_cancel(bool f) { }
|
||||
void cancel() { set_cancel(true); }
|
||||
void reset_cancel() { set_cancel(false); }
|
||||
virtual void set_progress_callback(progress_callback * callback) {}
|
||||
};
|
||||
|
||||
Z3_ast parse_smtlib2_stream(bool exec, Z3_context c, std::istream& is,
|
||||
unsigned num_sorts,
|
||||
Z3_symbol const sort_names[],
|
||||
Z3_sort const sorts[],
|
||||
unsigned num_decls,
|
||||
Z3_symbol const decl_names[],
|
||||
Z3_func_decl const decls[]) {
|
||||
Z3_TRY;
|
||||
cmd_context ctx(mk_c(c)->fparams(), false, &(mk_c(c)->m()));
|
||||
ctx.set_ignore_check(true);
|
||||
if (exec) {
|
||||
ctx.set_solver(alloc(z3_context_solver, *mk_c(c)));
|
||||
}
|
||||
for (unsigned i = 0; i < num_decls; ++i) {
|
||||
ctx.insert(to_symbol(decl_names[i]), to_func_decl(decls[i]));
|
||||
}
|
||||
for (unsigned i = 0; i < num_sorts; ++i) {
|
||||
psort* ps = ctx.pm().mk_psort_cnst(to_sort(sorts[i]));
|
||||
ctx.insert(ctx.pm().mk_psort_user_decl(0, to_symbol(sort_names[i]), ps));
|
||||
}
|
||||
if (!parse_smt2_commands(ctx, is)) {
|
||||
SET_ERROR_CODE(Z3_PARSER_ERROR);
|
||||
return of_ast(mk_c(c)->m().mk_true());
|
||||
}
|
||||
ptr_vector<expr>::const_iterator it = ctx.begin_assertions();
|
||||
ptr_vector<expr>::const_iterator end = ctx.end_assertions();
|
||||
unsigned size = static_cast<unsigned>(end - it);
|
||||
return of_ast(mk_c(c)->mk_and(size, it));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_parse_smtlib2_string(Z3_context c, Z3_string str,
|
||||
unsigned num_sorts,
|
||||
Z3_symbol const sort_names[],
|
||||
Z3_sort const sorts[],
|
||||
unsigned num_decls,
|
||||
Z3_symbol const decl_names[],
|
||||
Z3_func_decl const decls[]) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_parse_smtlib2_string(c, str, num_sorts, sort_names, sorts, num_decls, decl_names, decls);
|
||||
std::string s(str);
|
||||
std::istringstream is(s);
|
||||
Z3_ast r = parse_smtlib2_stream(false, c, is, num_sorts, sort_names, sorts, num_decls, decl_names, decls);
|
||||
RETURN_Z3(r);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_parse_smtlib2_file(Z3_context c, Z3_string file_name,
|
||||
unsigned num_sorts,
|
||||
Z3_symbol const sort_names[],
|
||||
Z3_sort const sorts[],
|
||||
unsigned num_decls,
|
||||
Z3_symbol const decl_names[],
|
||||
Z3_func_decl const decls[]) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_parse_smtlib2_string(c, file_name, num_sorts, sort_names, sorts, num_decls, decl_names, decls);
|
||||
std::ifstream is(file_name);
|
||||
if (!is) {
|
||||
SET_ERROR_CODE(Z3_PARSER_ERROR);
|
||||
return 0;
|
||||
}
|
||||
Z3_ast r = parse_smtlib2_stream(false, c, is, num_sorts, sort_names, sorts, num_decls, decl_names, decls);
|
||||
RETURN_Z3(r);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_exec_smtlib2_string(Z3_context c, Z3_string str,
|
||||
unsigned num_sorts,
|
||||
Z3_symbol sort_names[],
|
||||
Z3_sort sorts[],
|
||||
unsigned num_decls,
|
||||
Z3_symbol decl_names[],
|
||||
Z3_func_decl decls[]) {
|
||||
Z3_TRY;
|
||||
cmd_context ctx(mk_c(c)->fparams(), false, &(mk_c(c)->m()));
|
||||
std::string s(str);
|
||||
std::istringstream is(s);
|
||||
// No logging for this one, since it private.
|
||||
return parse_smtlib2_stream(true, c, is, num_sorts, sort_names, sorts, num_decls, decl_names, decls);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_exec_smtlib2_file(Z3_context c, Z3_string file_name,
|
||||
unsigned num_sorts,
|
||||
Z3_symbol sort_names[],
|
||||
Z3_sort sorts[],
|
||||
unsigned num_decls,
|
||||
Z3_symbol decl_names[],
|
||||
Z3_func_decl decls[]) {
|
||||
Z3_TRY;
|
||||
std::ifstream is(file_name);
|
||||
if (!is) {
|
||||
SET_ERROR_CODE(Z3_PARSER_ERROR);
|
||||
return 0;
|
||||
}
|
||||
// No logging for this one, since it private.
|
||||
return parse_smtlib2_stream(true, c, is, num_sorts, sort_names, sorts, num_decls, decl_names, decls);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
};
|
511
lib/api_quant.cpp
Normal file
511
lib/api_quant.cpp
Normal file
|
@ -0,0 +1,511 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
api_quant.cpp
|
||||
|
||||
Abstract:
|
||||
API for quantifiers
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2012-02-29.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include<iostream>
|
||||
#include"z3.h"
|
||||
#include"api_log_macros.h"
|
||||
#include"api_context.h"
|
||||
#include"api_util.h"
|
||||
#include"pattern_validation.h"
|
||||
#include"expr_abstract.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
Z3_ast Z3_API Z3_mk_quantifier(
|
||||
Z3_context c,
|
||||
Z3_bool is_forall,
|
||||
unsigned weight,
|
||||
unsigned num_patterns, Z3_pattern const patterns[],
|
||||
unsigned num_decls, Z3_sort const sorts[],
|
||||
Z3_symbol const decl_names[],
|
||||
Z3_ast body)
|
||||
{
|
||||
return Z3_mk_quantifier_ex(
|
||||
c,
|
||||
is_forall,
|
||||
weight,
|
||||
0,
|
||||
0,
|
||||
num_patterns, patterns,
|
||||
0, 0,
|
||||
num_decls, sorts,
|
||||
decl_names,
|
||||
body
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
Z3_ast mk_quantifier_ex_core(
|
||||
Z3_context c,
|
||||
Z3_bool is_forall,
|
||||
unsigned weight,
|
||||
Z3_symbol quantifier_id,
|
||||
Z3_symbol skolem_id,
|
||||
unsigned num_patterns, Z3_pattern const patterns[],
|
||||
unsigned num_no_patterns, Z3_ast const no_patterns[],
|
||||
unsigned num_decls, Z3_sort const sorts[],
|
||||
Z3_symbol const decl_names[],
|
||||
Z3_ast body) {
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
if (!mk_c(c)->m().is_bool(to_expr(body))) {
|
||||
SET_ERROR_CODE(Z3_SORT_ERROR);
|
||||
}
|
||||
if (num_patterns > 0 && num_no_patterns > 0) {
|
||||
SET_ERROR_CODE(Z3_INVALID_USAGE);
|
||||
}
|
||||
expr * const* ps = reinterpret_cast<expr * const*>(patterns);
|
||||
expr * const* no_ps = reinterpret_cast<expr * const*>(no_patterns);
|
||||
pattern_validator v(mk_c(c)->m());
|
||||
for (unsigned i = 0; i < num_patterns; i++) {
|
||||
if (!v(num_decls, ps[i])) {
|
||||
SET_ERROR_CODE(Z3_INVALID_PATTERN);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
sort* const* ts = reinterpret_cast<sort * const*>(sorts);
|
||||
svector<symbol> names;
|
||||
for (unsigned i = 0; i < num_decls; ++i) {
|
||||
names.push_back(to_symbol(decl_names[i]));
|
||||
}
|
||||
expr_ref result(mk_c(c)->m());
|
||||
if (num_decls > 0) {
|
||||
result = mk_c(c)->m().mk_quantifier(
|
||||
(0 != is_forall),
|
||||
names.size(), ts, names.c_ptr(), to_expr(body),
|
||||
weight,
|
||||
to_symbol(quantifier_id),
|
||||
to_symbol(skolem_id),
|
||||
num_patterns, ps,
|
||||
num_no_patterns, no_ps
|
||||
);
|
||||
}
|
||||
else {
|
||||
result = to_expr(body);
|
||||
}
|
||||
mk_c(c)->save_ast_trail(result.get());
|
||||
return of_ast(result.get());
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_mk_quantifier_ex(
|
||||
Z3_context c,
|
||||
Z3_bool is_forall,
|
||||
unsigned weight,
|
||||
Z3_symbol quantifier_id,
|
||||
Z3_symbol skolem_id,
|
||||
unsigned num_patterns, Z3_pattern const patterns[],
|
||||
unsigned num_no_patterns, Z3_ast const no_patterns[],
|
||||
unsigned num_decls, Z3_sort const sorts[],
|
||||
Z3_symbol const decl_names[],
|
||||
Z3_ast body)
|
||||
{
|
||||
LOG_Z3_mk_quantifier_ex(c, is_forall, weight, quantifier_id, skolem_id, num_patterns, patterns,
|
||||
num_no_patterns, no_patterns, num_decls, sorts, decl_names, body);
|
||||
Z3_ast r = mk_quantifier_ex_core(c, is_forall, weight, quantifier_id, skolem_id, num_patterns, patterns,
|
||||
num_no_patterns, no_patterns, num_decls, sorts, decl_names, body);
|
||||
RETURN_Z3(r);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_mk_forall(Z3_context c,
|
||||
unsigned weight,
|
||||
unsigned num_patterns, Z3_pattern const patterns[],
|
||||
unsigned num_decls, Z3_sort const types[],
|
||||
Z3_symbol const decl_names[],
|
||||
Z3_ast body) {
|
||||
return Z3_mk_quantifier(c, 1, weight, num_patterns, patterns, num_decls, types, decl_names, body);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_mk_exists(Z3_context c,
|
||||
unsigned weight,
|
||||
unsigned num_patterns, Z3_pattern const patterns[],
|
||||
unsigned num_decls, Z3_sort const types[],
|
||||
Z3_symbol const decl_names[],
|
||||
Z3_ast body) {
|
||||
return Z3_mk_quantifier(c, 0, weight, num_patterns, patterns, num_decls, types, decl_names, body);
|
||||
}
|
||||
|
||||
|
||||
Z3_ast Z3_API Z3_mk_quantifier_const_ex(Z3_context c,
|
||||
Z3_bool is_forall,
|
||||
unsigned weight,
|
||||
Z3_symbol quantifier_id,
|
||||
Z3_symbol skolem_id,
|
||||
unsigned num_bound,
|
||||
Z3_app const bound[],
|
||||
unsigned num_patterns,
|
||||
Z3_pattern const patterns[],
|
||||
unsigned num_no_patterns,
|
||||
Z3_ast const no_patterns[],
|
||||
Z3_ast body) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_quantifier_const_ex(c, is_forall, weight, quantifier_id, skolem_id, num_bound, bound, num_patterns, patterns,
|
||||
num_no_patterns, no_patterns, body);
|
||||
RESET_ERROR_CODE();
|
||||
svector<Z3_symbol> names;
|
||||
svector<Z3_sort> types;
|
||||
ptr_vector<expr> bound_asts;
|
||||
if (num_patterns > 0 && num_no_patterns > 0) {
|
||||
SET_ERROR_CODE(Z3_INVALID_USAGE);
|
||||
}
|
||||
for (unsigned i = 0; i < num_bound; ++i) {
|
||||
app* a = to_app(bound[i]);
|
||||
SASSERT(a->get_kind() == AST_APP);
|
||||
symbol s(to_app(a)->get_decl()->get_name());
|
||||
names.push_back(of_symbol(s));
|
||||
types.push_back(of_sort(mk_c(c)->m().get_sort(a)));
|
||||
bound_asts.push_back(a);
|
||||
if (a->get_family_id() != null_family_id || a->get_num_args() != 0) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
}
|
||||
// Abstract patterns
|
||||
svector<Z3_pattern> _patterns;
|
||||
expr_ref_vector pinned(mk_c(c)->m());
|
||||
for (unsigned i = 0; i < num_patterns; ++i) {
|
||||
expr_ref result(mk_c(c)->m());
|
||||
app* pat = to_pattern(patterns[i]);
|
||||
SASSERT(mk_c(c)->m().is_pattern(pat));
|
||||
expr_abstract(mk_c(c)->m(), 0, num_bound, bound_asts.c_ptr(), pat, result);
|
||||
SASSERT(result.get()->get_kind() == AST_APP);
|
||||
pinned.push_back(result.get());
|
||||
SASSERT(mk_c(c)->m().is_pattern(result.get()));
|
||||
_patterns.push_back(of_pattern(result.get()));
|
||||
}
|
||||
svector<Z3_ast> _no_patterns;
|
||||
for (unsigned i = 0; i < num_no_patterns; ++i) {
|
||||
expr_ref result(mk_c(c)->m());
|
||||
if (!is_app(to_expr(no_patterns[i]))) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
app* pat = to_app(to_expr(no_patterns[i]));
|
||||
expr_abstract(mk_c(c)->m(), 0, num_bound, bound_asts.c_ptr(), pat, result);
|
||||
SASSERT(result.get()->get_kind() == AST_APP);
|
||||
pinned.push_back(result.get());
|
||||
_no_patterns.push_back(of_ast(result.get()));
|
||||
}
|
||||
expr_ref abs_body(mk_c(c)->m());
|
||||
expr_abstract(mk_c(c)->m(), 0, num_bound, bound_asts.c_ptr(), to_expr(body), abs_body);
|
||||
|
||||
Z3_ast result = mk_quantifier_ex_core(c, is_forall, weight,
|
||||
quantifier_id,
|
||||
skolem_id,
|
||||
num_patterns, _patterns.c_ptr(),
|
||||
num_no_patterns, _no_patterns.c_ptr(),
|
||||
names.size(), types.c_ptr(), names.c_ptr(),
|
||||
of_ast(abs_body.get()));
|
||||
RETURN_Z3(result);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_mk_quantifier_const(Z3_context c,
|
||||
Z3_bool is_forall,
|
||||
unsigned weight,
|
||||
unsigned num_bound,
|
||||
Z3_app const bound[],
|
||||
unsigned num_patterns,
|
||||
Z3_pattern const patterns[],
|
||||
Z3_ast body) {
|
||||
return Z3_mk_quantifier_const_ex(c, is_forall, weight, 0, 0,
|
||||
num_bound, bound,
|
||||
num_patterns, patterns,
|
||||
0, 0,
|
||||
body);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_mk_forall_const(Z3_context c,
|
||||
unsigned weight,
|
||||
unsigned num_bound,
|
||||
Z3_app const bound[],
|
||||
unsigned num_patterns,
|
||||
Z3_pattern const patterns[],
|
||||
Z3_ast body) {
|
||||
return Z3_mk_quantifier_const(c, true, weight, num_bound, bound, num_patterns, patterns, body);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_mk_exists_const(Z3_context c,
|
||||
unsigned weight,
|
||||
unsigned num_bound,
|
||||
Z3_app const bound[],
|
||||
unsigned num_patterns,
|
||||
Z3_pattern const patterns[],
|
||||
Z3_ast body) {
|
||||
return Z3_mk_quantifier_const(c, false, weight, num_bound, bound, num_patterns, patterns, body);
|
||||
}
|
||||
|
||||
Z3_pattern Z3_API Z3_mk_pattern(Z3_context c, unsigned num_patterns, Z3_ast const terms[]) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_pattern(c, num_patterns, terms);
|
||||
RESET_ERROR_CODE();
|
||||
for (unsigned i = 0; i < num_patterns; ++i) {
|
||||
if (!is_app(to_expr(terms[i]))) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
}
|
||||
app* a = mk_c(c)->m().mk_pattern(num_patterns, reinterpret_cast<app*const*>(to_exprs(terms)));
|
||||
mk_c(c)->save_ast_trail(a);
|
||||
RETURN_Z3(of_pattern(a));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_mk_bound(Z3_context c, unsigned index, Z3_sort ty) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_bound(c, index, ty);
|
||||
RESET_ERROR_CODE();
|
||||
ast* a = mk_c(c)->m().mk_var(index, to_sort(ty));
|
||||
mk_c(c)->save_ast_trail(a);
|
||||
RETURN_Z3(of_ast(a));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_bool Z3_API Z3_is_quantifier_forall(Z3_context c, Z3_ast a) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_is_quantifier_forall(c, a);
|
||||
RESET_ERROR_CODE();
|
||||
ast * _a = to_ast(a);
|
||||
if (_a->get_kind() == AST_QUANTIFIER) {
|
||||
return to_quantifier(_a)->is_forall();
|
||||
}
|
||||
else {
|
||||
SET_ERROR_CODE(Z3_SORT_ERROR);
|
||||
return Z3_FALSE;
|
||||
}
|
||||
Z3_CATCH_RETURN(Z3_FALSE);
|
||||
}
|
||||
|
||||
unsigned Z3_API Z3_get_quantifier_weight(Z3_context c, Z3_ast a) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_quantifier_weight(c, a);
|
||||
RESET_ERROR_CODE();
|
||||
ast * _a = to_ast(a);
|
||||
if (_a->get_kind() == AST_QUANTIFIER) {
|
||||
return to_quantifier(_a)->get_weight();
|
||||
}
|
||||
else {
|
||||
SET_ERROR_CODE(Z3_SORT_ERROR);
|
||||
return 0;
|
||||
}
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
unsigned Z3_API Z3_get_quantifier_num_patterns(Z3_context c, Z3_ast a) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_quantifier_num_patterns(c, a);
|
||||
RESET_ERROR_CODE();
|
||||
ast * _a = to_ast(a);
|
||||
if (_a->get_kind() == AST_QUANTIFIER) {
|
||||
return to_quantifier(_a)->get_num_patterns();
|
||||
}
|
||||
else {
|
||||
SET_ERROR_CODE(Z3_SORT_ERROR);
|
||||
return 0;
|
||||
}
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_pattern Z3_API Z3_get_quantifier_pattern_ast(Z3_context c, Z3_ast a, unsigned i) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_quantifier_pattern_ast(c, a, i);
|
||||
RESET_ERROR_CODE();
|
||||
ast * _a = to_ast(a);
|
||||
if (_a->get_kind() == AST_QUANTIFIER) {
|
||||
Z3_pattern r = of_pattern(to_quantifier(_a)->get_patterns()[i]);
|
||||
RETURN_Z3(r);
|
||||
}
|
||||
else {
|
||||
SET_ERROR_CODE(Z3_SORT_ERROR);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
|
||||
unsigned Z3_API Z3_get_quantifier_num_no_patterns(Z3_context c, Z3_ast a) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_quantifier_num_no_patterns(c, a);
|
||||
RESET_ERROR_CODE();
|
||||
ast * _a = to_ast(a);
|
||||
if (_a->get_kind() == AST_QUANTIFIER) {
|
||||
return to_quantifier(_a)->get_num_no_patterns();
|
||||
}
|
||||
else {
|
||||
SET_ERROR_CODE(Z3_SORT_ERROR);
|
||||
return 0;
|
||||
}
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_get_quantifier_no_pattern_ast(Z3_context c, Z3_ast a, unsigned i) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_quantifier_no_pattern_ast(c, a, i);
|
||||
RESET_ERROR_CODE();
|
||||
ast * _a = to_ast(a);
|
||||
if (_a->get_kind() == AST_QUANTIFIER) {
|
||||
Z3_ast r = of_ast(to_quantifier(_a)->get_no_pattern(i));
|
||||
RETURN_Z3(r);
|
||||
}
|
||||
else {
|
||||
SET_ERROR_CODE(Z3_SORT_ERROR);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_symbol Z3_API Z3_get_quantifier_bound_name(Z3_context c, Z3_ast a, unsigned i) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_quantifier_bound_name(c, a, i);
|
||||
RESET_ERROR_CODE();
|
||||
ast * _a = to_ast(a);
|
||||
if (_a->get_kind() == AST_QUANTIFIER) {
|
||||
return of_symbol(to_quantifier(_a)->get_decl_names()[i]);
|
||||
}
|
||||
else {
|
||||
SET_ERROR_CODE(Z3_SORT_ERROR);
|
||||
return 0;
|
||||
}
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_sort Z3_API Z3_get_quantifier_bound_sort(Z3_context c, Z3_ast a, unsigned i) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_quantifier_bound_sort(c, a, i);
|
||||
RESET_ERROR_CODE();
|
||||
ast * _a = to_ast(a);
|
||||
if (_a->get_kind() == AST_QUANTIFIER) {
|
||||
Z3_sort r = of_sort(to_quantifier(_a)->get_decl_sort(i));
|
||||
RETURN_Z3(r);
|
||||
}
|
||||
else {
|
||||
SET_ERROR_CODE(Z3_SORT_ERROR);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_get_quantifier_body(Z3_context c, Z3_ast a) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_quantifier_body(c, a);
|
||||
RESET_ERROR_CODE();
|
||||
ast * _a = to_ast(a);
|
||||
if (_a->get_kind() == AST_QUANTIFIER) {
|
||||
Z3_ast r = of_ast(to_quantifier(_a)->get_expr());
|
||||
RETURN_Z3(r);
|
||||
}
|
||||
else {
|
||||
SET_ERROR_CODE(Z3_SORT_ERROR);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
unsigned Z3_API Z3_get_quantifier_num_bound(Z3_context c, Z3_ast a) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_quantifier_num_bound(c, a);
|
||||
RESET_ERROR_CODE();
|
||||
ast * _a = to_ast(a);
|
||||
if (_a->get_kind() == AST_QUANTIFIER) {
|
||||
|
||||
return to_quantifier(_a)->get_num_decls();
|
||||
}
|
||||
else {
|
||||
SET_ERROR_CODE(Z3_SORT_ERROR);
|
||||
return 0;
|
||||
}
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
unsigned Z3_API Z3_get_pattern_num_terms(Z3_context c, Z3_pattern p) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_pattern_num_terms(c, p);
|
||||
RESET_ERROR_CODE();
|
||||
app* _p = to_pattern(p);
|
||||
if (mk_c(c)->m().is_pattern(_p)) {
|
||||
return _p->get_num_args();
|
||||
}
|
||||
else {
|
||||
SET_ERROR_CODE(Z3_SORT_ERROR);
|
||||
return 0;
|
||||
}
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_get_pattern(Z3_context c, Z3_pattern p, unsigned idx) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_pattern(c, p, idx);
|
||||
RESET_ERROR_CODE();
|
||||
app* _p = to_pattern(p);
|
||||
if (mk_c(c)->m().is_pattern(_p)) {
|
||||
Z3_ast r = of_ast(_p->get_arg(idx));
|
||||
RETURN_Z3(r);
|
||||
}
|
||||
else {
|
||||
SET_ERROR_CODE(Z3_SORT_ERROR);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_func_decl Z3_API Z3_mk_injective_function(Z3_context c,
|
||||
Z3_symbol s,
|
||||
unsigned domain_size,
|
||||
Z3_sort const domain[],
|
||||
Z3_sort range) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_injective_function(c, s, domain_size, domain, range);
|
||||
RESET_ERROR_CODE();
|
||||
ast_manager & m = mk_c(c)->m();
|
||||
mk_c(c)->reset_last_result();
|
||||
sort* range_ = to_sort(range);
|
||||
func_decl* d = m.mk_func_decl(to_symbol(s), domain_size, to_sorts(domain), range_);
|
||||
expr_ref_vector args(m);
|
||||
expr_ref fn(m), body(m);
|
||||
vector<symbol> names;
|
||||
for (unsigned i = 0; i < domain_size; ++i) {
|
||||
unsigned idx = domain_size-i-1;
|
||||
args.push_back(m.mk_var(idx, to_sort(domain[i])));
|
||||
names.push_back(symbol(idx));
|
||||
}
|
||||
fn = m.mk_app(d, args.size(), args.c_ptr());
|
||||
|
||||
for (unsigned i = 0; i < domain_size; ++i) {
|
||||
expr* arg = args[i].get();
|
||||
sort* dom = m.get_sort(arg);
|
||||
func_decl* inv = m.mk_fresh_func_decl(symbol("inv"), to_symbol(s), 1, &range_, dom);
|
||||
body = m.mk_eq(m.mk_app(inv, fn.get()), arg);
|
||||
body = m.mk_forall(args.size(), to_sorts(domain), names.c_ptr(), body.get());
|
||||
mk_c(c)->save_multiple_ast_trail(body.get());
|
||||
mk_c(c)->assert_cnstr(body.get());
|
||||
}
|
||||
mk_c(c)->save_multiple_ast_trail(d);
|
||||
RETURN_Z3(of_func_decl(d));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_pattern_to_ast(Z3_context c, Z3_pattern p) {
|
||||
RESET_ERROR_CODE();
|
||||
return (Z3_ast)(p);
|
||||
}
|
||||
|
||||
char const * Z3_API Z3_pattern_to_string(Z3_context c, Z3_pattern p) {
|
||||
return Z3_ast_to_string(c, reinterpret_cast<Z3_ast>(p));
|
||||
}
|
||||
|
||||
};
|
322
lib/api_solver.cpp
Normal file
322
lib/api_solver.cpp
Normal file
|
@ -0,0 +1,322 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
api_solver.cpp
|
||||
|
||||
Abstract:
|
||||
New solver API
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2012-03-07.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include<iostream>
|
||||
#include"z3.h"
|
||||
#include"api_log_macros.h"
|
||||
#include"api_context.h"
|
||||
#include"api_tactic.h"
|
||||
#include"api_solver.h"
|
||||
#include"api_model.h"
|
||||
#include"api_stats.h"
|
||||
#include"api_ast_vector.h"
|
||||
#include"tactic2solver.h"
|
||||
#include"scoped_ctrl_c.h"
|
||||
#include"cancel_eh.h"
|
||||
#include"scoped_timer.h"
|
||||
#include"smt_strategic_solver.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
Z3_solver Z3_API Z3_mk_simple_solver(Z3_context c) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_simple_solver(c);
|
||||
RESET_ERROR_CODE();
|
||||
Z3_solver_ref * s = alloc(Z3_solver_ref);
|
||||
s->m_solver = mk_default_solver();
|
||||
s->m_solver->set_front_end_params(mk_c(c)->fparams());
|
||||
s->m_solver->init(mk_c(c)->m(), symbol::null);
|
||||
mk_c(c)->save_object(s);
|
||||
Z3_solver r = of_solver(s);
|
||||
RETURN_Z3(r);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_solver Z3_API Z3_mk_solver(Z3_context c) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_solver(c);
|
||||
RESET_ERROR_CODE();
|
||||
Z3_solver_ref * s = alloc(Z3_solver_ref);
|
||||
s->m_solver = mk_smt_strategic_solver();
|
||||
s->m_solver->set_front_end_params(mk_c(c)->fparams());
|
||||
s->m_solver->init(mk_c(c)->m(), symbol::null);
|
||||
mk_c(c)->save_object(s);
|
||||
Z3_solver r = of_solver(s);
|
||||
RETURN_Z3(r);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_solver Z3_API Z3_mk_solver_for_logic(Z3_context c, Z3_symbol logic) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_solver_for_logic(c, logic);
|
||||
RESET_ERROR_CODE();
|
||||
Z3_solver_ref * s = alloc(Z3_solver_ref);
|
||||
s->m_solver = mk_smt_strategic_solver(true /* force solver to use tactics even when auto_config is disabled */);
|
||||
s->m_solver->set_front_end_params(mk_c(c)->fparams());
|
||||
s->m_solver->init(mk_c(c)->m(), to_symbol(logic));
|
||||
mk_c(c)->save_object(s);
|
||||
Z3_solver r = of_solver(s);
|
||||
RETURN_Z3(r);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_solver Z3_API Z3_mk_solver_from_tactic(Z3_context c, Z3_tactic t) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_solver_from_tactic(c, t);
|
||||
RESET_ERROR_CODE();
|
||||
Z3_solver_ref * s = alloc(Z3_solver_ref);
|
||||
s->m_solver = alloc(tactic2solver_api, to_tactic_ref(t));
|
||||
s->m_solver->set_front_end_params(mk_c(c)->fparams());
|
||||
s->m_solver->init(mk_c(c)->m(), symbol::null);
|
||||
mk_c(c)->save_object(s);
|
||||
Z3_solver r = of_solver(s);
|
||||
RETURN_Z3(r);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_string Z3_API Z3_solver_get_help(Z3_context c, Z3_solver s) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_solver_get_help(c, s);
|
||||
RESET_ERROR_CODE();
|
||||
std::ostringstream buffer;
|
||||
param_descrs descrs;
|
||||
to_solver_ref(s)->collect_param_descrs(descrs);
|
||||
descrs.display(buffer);
|
||||
return mk_c(c)->mk_external_string(buffer.str());
|
||||
Z3_CATCH_RETURN("");
|
||||
}
|
||||
|
||||
Z3_param_descrs Z3_API Z3_solver_get_param_descrs(Z3_context c, Z3_solver s) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_solver_get_param_descrs(c, s);
|
||||
RESET_ERROR_CODE();
|
||||
Z3_param_descrs_ref * d = alloc(Z3_param_descrs_ref);
|
||||
mk_c(c)->save_object(d);
|
||||
to_solver_ref(s)->collect_param_descrs(d->m_descrs);
|
||||
Z3_param_descrs r = of_param_descrs(d);
|
||||
RETURN_Z3(r);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
void Z3_API Z3_solver_set_params(Z3_context c, Z3_solver s, Z3_params p) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_solver_set_params(c, s, p);
|
||||
RESET_ERROR_CODE();
|
||||
to_solver_ref(s)->updt_params(to_param_ref(p));
|
||||
to_solver(s)->m_params = to_param_ref(p);
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_solver_inc_ref(Z3_context c, Z3_solver s) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_solver_inc_ref(c, s);
|
||||
RESET_ERROR_CODE();
|
||||
to_solver(s)->inc_ref();
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_solver_dec_ref(Z3_context c, Z3_solver s) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_solver_dec_ref(c, s);
|
||||
RESET_ERROR_CODE();
|
||||
to_solver(s)->dec_ref();
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_solver_push(Z3_context c, Z3_solver s) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_solver_push(c, s);
|
||||
RESET_ERROR_CODE();
|
||||
to_solver_ref(s)->push();
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_solver_pop(Z3_context c, Z3_solver s, unsigned n) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_solver_pop(c, s, n);
|
||||
RESET_ERROR_CODE();
|
||||
if (n > to_solver_ref(s)->get_scope_level()) {
|
||||
SET_ERROR_CODE(Z3_IOB);
|
||||
return;
|
||||
}
|
||||
if (n > 0)
|
||||
to_solver_ref(s)->pop(n);
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_solver_reset(Z3_context c, Z3_solver s) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_solver_reset(c, s);
|
||||
RESET_ERROR_CODE();
|
||||
to_solver_ref(s)->reset();
|
||||
to_solver_ref(s)->init(mk_c(c)->m(), symbol::null);
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
unsigned Z3_API Z3_solver_get_num_scopes(Z3_context c, Z3_solver s) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_solver_get_num_scopes(c, s);
|
||||
RESET_ERROR_CODE();
|
||||
return to_solver_ref(s)->get_scope_level();
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
void Z3_API Z3_solver_assert(Z3_context c, Z3_solver s, Z3_ast a) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_solver_assert(c, s, a);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_FORMULA(a,);
|
||||
to_solver_ref(s)->assert_expr(to_expr(a));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
Z3_ast_vector Z3_API Z3_solver_get_assertions(Z3_context c, Z3_solver s) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_solver_get_assertions(c, s);
|
||||
RESET_ERROR_CODE();
|
||||
Z3_ast_vector_ref * v = alloc(Z3_ast_vector_ref, mk_c(c)->m());
|
||||
mk_c(c)->save_object(v);
|
||||
unsigned sz = to_solver_ref(s)->get_num_assertions();
|
||||
for (unsigned i = 0; i < sz; i++) {
|
||||
v->m_ast_vector.push_back(to_solver_ref(s)->get_assertion(i));
|
||||
}
|
||||
RETURN_Z3(of_ast_vector(v));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
static Z3_lbool _solver_check(Z3_context c, Z3_solver s, unsigned num_assumptions, Z3_ast const assumptions[]) {
|
||||
for (unsigned i = 0; i < num_assumptions; i++) {
|
||||
if (!is_expr(to_ast(assumptions[i]))) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
return Z3_L_UNDEF;
|
||||
}
|
||||
}
|
||||
expr * const * _assumptions = to_exprs(assumptions);
|
||||
to_solver_ref(s)->set_produce_models(to_solver(s)->m_params.get_bool(":model", true));
|
||||
to_solver_ref(s)->set_produce_proofs(mk_c(c)->m().proofs_enabled());
|
||||
to_solver_ref(s)->set_produce_unsat_cores(num_assumptions > 0);
|
||||
unsigned timeout = to_solver(s)->m_params.get_uint(":timeout", UINT_MAX);
|
||||
bool use_ctrl_c = to_solver(s)->m_params.get_bool(":ctrl-c", false);
|
||||
cancel_eh<solver> eh(*to_solver_ref(s));
|
||||
api::context::set_interruptable(*(mk_c(c)), eh);
|
||||
lbool result;
|
||||
{
|
||||
scoped_ctrl_c ctrlc(eh, false, use_ctrl_c);
|
||||
scoped_timer timer(timeout, &eh);
|
||||
try {
|
||||
result = to_solver_ref(s)->check_sat(num_assumptions, _assumptions);
|
||||
}
|
||||
catch (z3_exception & ex) {
|
||||
mk_c(c)->handle_exception(ex);
|
||||
return Z3_L_UNDEF;
|
||||
}
|
||||
}
|
||||
return static_cast<Z3_lbool>(result);
|
||||
}
|
||||
|
||||
Z3_lbool Z3_API Z3_solver_check(Z3_context c, Z3_solver s) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_solver_check(c, s);
|
||||
RESET_ERROR_CODE();
|
||||
return _solver_check(c, s, 0, 0);
|
||||
Z3_CATCH_RETURN(Z3_L_UNDEF);
|
||||
}
|
||||
|
||||
Z3_lbool Z3_API Z3_solver_check_assumptions(Z3_context c, Z3_solver s, unsigned num_assumptions, Z3_ast const assumptions[]) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_solver_check_assumptions(c, s, num_assumptions, assumptions);
|
||||
RESET_ERROR_CODE();
|
||||
return _solver_check(c, s, num_assumptions, assumptions);
|
||||
Z3_CATCH_RETURN(Z3_L_UNDEF);
|
||||
}
|
||||
|
||||
Z3_model Z3_API Z3_solver_get_model(Z3_context c, Z3_solver s) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_solver_get_model(c, s);
|
||||
RESET_ERROR_CODE();
|
||||
model_ref _m;
|
||||
to_solver_ref(s)->get_model(_m);
|
||||
if (!_m) {
|
||||
SET_ERROR_CODE(Z3_INVALID_USAGE);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
Z3_model_ref * m_ref = alloc(Z3_model_ref);
|
||||
m_ref->m_model = _m;
|
||||
mk_c(c)->save_object(m_ref);
|
||||
RETURN_Z3(of_model(m_ref));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_solver_get_proof(Z3_context c, Z3_solver s) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_solver_get_proof(c, s);
|
||||
RESET_ERROR_CODE();
|
||||
proof * p = to_solver_ref(s)->get_proof();
|
||||
if (!p) {
|
||||
SET_ERROR_CODE(Z3_INVALID_USAGE);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
mk_c(c)->save_ast_trail(p);
|
||||
RETURN_Z3(of_ast(p));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast_vector Z3_API Z3_solver_get_unsat_core(Z3_context c, Z3_solver s) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_solver_get_unsat_core(c, s);
|
||||
RESET_ERROR_CODE();
|
||||
ptr_vector<expr> core;
|
||||
to_solver_ref(s)->get_unsat_core(core);
|
||||
Z3_ast_vector_ref * v = alloc(Z3_ast_vector_ref, mk_c(c)->m());
|
||||
mk_c(c)->save_object(v);
|
||||
for (unsigned i = 0; i < core.size(); i++) {
|
||||
v->m_ast_vector.push_back(core[i]);
|
||||
}
|
||||
RETURN_Z3(of_ast_vector(v));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_string Z3_API Z3_solver_get_reason_unknown(Z3_context c, Z3_solver s) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_solver_get_reason_unknown(c, s);
|
||||
RESET_ERROR_CODE();
|
||||
return mk_c(c)->mk_external_string(to_solver_ref(s)->reason_unknown());
|
||||
Z3_CATCH_RETURN("");
|
||||
}
|
||||
|
||||
Z3_stats Z3_API Z3_solver_get_statistics(Z3_context c, Z3_solver s) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_solver_get_statistics(c, s);
|
||||
RESET_ERROR_CODE();
|
||||
Z3_stats_ref * st = alloc(Z3_stats_ref);
|
||||
to_solver_ref(s)->collect_statistics(st->m_stats);
|
||||
mk_c(c)->save_object(st);
|
||||
Z3_stats r = of_stats(st);
|
||||
RETURN_Z3(r);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_string Z3_API Z3_solver_to_string(Z3_context c, Z3_solver s) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_solver_to_string(c, s);
|
||||
RESET_ERROR_CODE();
|
||||
std::ostringstream buffer;
|
||||
to_solver_ref(s)->display(buffer);
|
||||
return mk_c(c)->mk_external_string(buffer.str());
|
||||
Z3_CATCH_RETURN("");
|
||||
}
|
||||
};
|
35
lib/api_solver.h
Normal file
35
lib/api_solver.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
api_solver.h
|
||||
|
||||
Abstract:
|
||||
New solver API
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2012-03-07.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _API_SOLVER_H_
|
||||
#define _API_SOLVER_H_
|
||||
|
||||
#include"api_util.h"
|
||||
#include"solver.h"
|
||||
|
||||
struct Z3_solver_ref : public api::object {
|
||||
solver * m_solver;
|
||||
params_ref m_params;
|
||||
Z3_solver_ref():m_solver(0) {}
|
||||
virtual ~Z3_solver_ref() { dealloc(m_solver); }
|
||||
};
|
||||
|
||||
inline Z3_solver_ref * to_solver(Z3_solver s) { return reinterpret_cast<Z3_solver_ref *>(s); }
|
||||
inline Z3_solver of_solver(Z3_solver_ref * s) { return reinterpret_cast<Z3_solver>(s); }
|
||||
inline solver * to_solver_ref(Z3_solver s) { return to_solver(s)->m_solver; }
|
||||
|
||||
#endif
|
365
lib/api_solver_old.cpp
Normal file
365
lib/api_solver_old.cpp
Normal file
|
@ -0,0 +1,365 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
api_solver_old.cpp
|
||||
|
||||
Abstract:
|
||||
OLD API for using solvers.
|
||||
|
||||
This has been deprecated
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2012-02-29.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include<iostream>
|
||||
#include"z3.h"
|
||||
#include"api_log_macros.h"
|
||||
#include"api_context.h"
|
||||
#include"api_model.h"
|
||||
#include"smt_implied_equalities.h"
|
||||
#include"cancel_eh.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
void Z3_API Z3_push(Z3_context c) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_push(c);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_SEARCHING(c);
|
||||
mk_c(c)->push();
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_pop(Z3_context c, unsigned num_scopes) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_pop(c, num_scopes);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_SEARCHING(c);
|
||||
if (num_scopes > mk_c(c)->get_solver().get_scope_level()) {
|
||||
SET_ERROR_CODE(Z3_IOB);
|
||||
return;
|
||||
}
|
||||
if (num_scopes > 0) {
|
||||
mk_c(c)->pop(num_scopes);
|
||||
}
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
unsigned Z3_API Z3_get_num_scopes(Z3_context c) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_num_scopes(c);
|
||||
RESET_ERROR_CODE();
|
||||
return mk_c(c)->get_num_scopes();
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
void Z3_API Z3_assert_cnstr(Z3_context c, Z3_ast a) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_assert_cnstr(c, a);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_FORMULA(a,);
|
||||
mk_c(c)->assert_cnstr(to_expr(a));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
Z3_lbool Z3_API Z3_check_and_get_model(Z3_context c, Z3_model * m) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_check_and_get_model(c, m);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_SEARCHING(c);
|
||||
cancel_eh<smt::solver> eh(mk_c(c)->get_solver());
|
||||
api::context::set_interruptable(*(mk_c(c)), eh);
|
||||
flet<bool> _model(mk_c(c)->fparams().m_model, true);
|
||||
lbool result;
|
||||
try {
|
||||
model_ref _m;
|
||||
result = mk_c(c)->check(_m);
|
||||
if (m) {
|
||||
if (_m) {
|
||||
Z3_model_ref * m_ref = alloc(Z3_model_ref);
|
||||
m_ref->m_model = _m;
|
||||
// Must bump reference counter for backward compatibility reasons.
|
||||
// Don't need to invoke save_object, since the counter was bumped
|
||||
m_ref->inc_ref();
|
||||
*m = of_model(m_ref);
|
||||
}
|
||||
else {
|
||||
*m = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (z3_exception & ex) {
|
||||
mk_c(c)->handle_exception(ex);
|
||||
RETURN_Z3_check_and_get_model static_cast<Z3_lbool>(l_undef);
|
||||
}
|
||||
RETURN_Z3_check_and_get_model static_cast<Z3_lbool>(result);
|
||||
Z3_CATCH_RETURN(Z3_L_UNDEF);
|
||||
}
|
||||
|
||||
Z3_lbool Z3_API Z3_check(Z3_context c) {
|
||||
Z3_TRY;
|
||||
// This is just syntax sugar...
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_SEARCHING(c);
|
||||
Z3_lbool r = Z3_check_and_get_model(c, 0);
|
||||
return r;
|
||||
Z3_CATCH_RETURN(Z3_L_UNDEF);
|
||||
}
|
||||
|
||||
Z3_lbool Z3_API Z3_get_implied_equalities(Z3_context c,
|
||||
unsigned num_terms,
|
||||
Z3_ast const terms[],
|
||||
unsigned class_ids[]) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_implied_equalities(c, num_terms, terms, class_ids);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_SEARCHING(c);
|
||||
lbool result = smt::implied_equalities(mk_c(c)->get_solver(), num_terms, to_exprs(terms), class_ids);
|
||||
return static_cast<Z3_lbool>(result);
|
||||
Z3_CATCH_RETURN(Z3_L_UNDEF);
|
||||
}
|
||||
|
||||
|
||||
Z3_lbool Z3_API Z3_check_assumptions(Z3_context c,
|
||||
unsigned num_assumptions, Z3_ast const assumptions[],
|
||||
Z3_model * m, Z3_ast* proof,
|
||||
unsigned* core_size, Z3_ast core[]) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_check_assumptions(c, num_assumptions, assumptions, m, proof, core_size, core);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_SEARCHING(c);
|
||||
expr * const* _assumptions = to_exprs(assumptions);
|
||||
flet<bool> _model(mk_c(c)->fparams().m_model, true);
|
||||
cancel_eh<smt::solver> eh(mk_c(c)->get_solver());
|
||||
api::context::set_interruptable(*(mk_c(c)), eh);
|
||||
lbool result;
|
||||
result = mk_c(c)->get_solver().check(num_assumptions, _assumptions);
|
||||
if (result != l_false && m) {
|
||||
model_ref _m;
|
||||
mk_c(c)->get_solver().get_model(_m);
|
||||
if (_m) {
|
||||
Z3_model_ref * m_ref = alloc(Z3_model_ref);
|
||||
m_ref->m_model = _m;
|
||||
// Must bump reference counter for backward compatibility reasons.
|
||||
// Don't need to invoke save_object, since the counter was bumped
|
||||
m_ref->inc_ref();
|
||||
*m = of_model(m_ref);
|
||||
}
|
||||
else {
|
||||
*m = 0;
|
||||
}
|
||||
}
|
||||
if (result == l_false && core_size) {
|
||||
*core_size = mk_c(c)->get_solver().get_unsat_core_size();
|
||||
if (*core_size > num_assumptions) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
}
|
||||
for (unsigned i = 0; i < *core_size; ++i) {
|
||||
core[i] = of_ast(mk_c(c)->get_solver().get_unsat_core_expr(i));
|
||||
}
|
||||
}
|
||||
else if (core_size) {
|
||||
*core_size = 0;
|
||||
}
|
||||
if (result == l_false && proof) {
|
||||
*proof = of_ast(mk_c(c)->get_solver().get_proof());
|
||||
}
|
||||
else if (proof) {
|
||||
*proof = 0; // breaks abstraction.
|
||||
}
|
||||
RETURN_Z3_check_assumptions static_cast<Z3_lbool>(result);
|
||||
Z3_CATCH_RETURN(Z3_L_UNDEF);
|
||||
}
|
||||
|
||||
Z3_search_failure Z3_API Z3_get_search_failure(Z3_context c) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_search_failure(c);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_SEARCHING(c);
|
||||
smt::failure f = mk_c(c)->get_solver().last_failure();
|
||||
return api::mk_Z3_search_failure(f);
|
||||
Z3_CATCH_RETURN(Z3_UNKNOWN);
|
||||
}
|
||||
|
||||
class labeled_literal {
|
||||
expr_ref m_literal;
|
||||
symbol m_label;
|
||||
bool m_enabled;
|
||||
public:
|
||||
labeled_literal(ast_manager& m, expr* l, symbol const& n) : m_literal(l,m), m_label(n), m_enabled(true) {}
|
||||
labeled_literal(ast_manager& m, expr* l) : m_literal(l,m), m_label(), m_enabled(true) {}
|
||||
bool is_enabled() const { return m_enabled; }
|
||||
void disable() { m_enabled = false; }
|
||||
symbol const& get_label() const { return m_label; }
|
||||
expr* get_literal() { return m_literal.get(); }
|
||||
};
|
||||
|
||||
typedef vector<labeled_literal> labels;
|
||||
|
||||
Z3_literals Z3_API Z3_get_relevant_labels(Z3_context c) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_relevant_labels(c);
|
||||
RESET_ERROR_CODE();
|
||||
buffer<symbol> labl_syms;
|
||||
ast_manager& m = mk_c(c)->m();
|
||||
expr_ref_vector lits(m);
|
||||
mk_c(c)->get_solver().get_relevant_labels(0, labl_syms);
|
||||
mk_c(c)->get_solver().get_relevant_labeled_literals(mk_c(c)->fparams().m_at_labels_cex, lits);
|
||||
labels* lbls = alloc(labels);
|
||||
SASSERT(labl_syms.size() == lits.size());
|
||||
for (unsigned i = 0; i < lits.size(); ++i) {
|
||||
lbls->push_back(labeled_literal(m,lits[i].get(), labl_syms[i]));
|
||||
}
|
||||
RETURN_Z3(reinterpret_cast<Z3_literals>(lbls));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_literals Z3_API Z3_get_relevant_literals(Z3_context c) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_relevant_literals(c);
|
||||
RESET_ERROR_CODE();
|
||||
ast_manager& m = mk_c(c)->m();
|
||||
expr_ref_vector lits(m);
|
||||
mk_c(c)->get_solver().get_relevant_literals(lits);
|
||||
labels* lbls = alloc(labels);
|
||||
for (unsigned i = 0; i < lits.size(); ++i) {
|
||||
lbls->push_back(labeled_literal(m,lits[i].get()));
|
||||
}
|
||||
RETURN_Z3(reinterpret_cast<Z3_literals>(lbls));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_literals Z3_API Z3_get_guessed_literals(Z3_context c) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_guessed_literals(c);
|
||||
RESET_ERROR_CODE();
|
||||
ast_manager& m = mk_c(c)->m();
|
||||
expr_ref_vector lits(m);
|
||||
mk_c(c)->get_solver().get_guessed_literals(lits);
|
||||
labels* lbls = alloc(labels);
|
||||
for (unsigned i = 0; i < lits.size(); ++i) {
|
||||
lbls->push_back(labeled_literal(m,lits[i].get()));
|
||||
}
|
||||
RETURN_Z3(reinterpret_cast<Z3_literals>(lbls));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
void Z3_API Z3_del_literals(Z3_context c, Z3_literals lbls) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_del_literals(c, lbls);
|
||||
RESET_ERROR_CODE();
|
||||
dealloc(reinterpret_cast<labels*>(lbls));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
unsigned Z3_API Z3_get_num_literals(Z3_context c,Z3_literals lbls) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_num_literals(c, lbls);
|
||||
RESET_ERROR_CODE();
|
||||
return reinterpret_cast<labels*>(lbls)->size();
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_symbol Z3_API Z3_get_label_symbol(Z3_context c,Z3_literals lbls, unsigned idx) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_label_symbol(c, lbls, idx);
|
||||
RESET_ERROR_CODE();
|
||||
return of_symbol((*reinterpret_cast<labels*>(lbls))[idx].get_label());
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_get_literal(Z3_context c,Z3_literals lbls, unsigned idx) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_literal(c, lbls, idx);
|
||||
RESET_ERROR_CODE();
|
||||
expr* e = (*reinterpret_cast<labels*>(lbls))[idx].get_literal();
|
||||
mk_c(c)->save_ast_trail(e);
|
||||
RETURN_Z3(of_ast(e));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
void Z3_API Z3_disable_literal(Z3_context c, Z3_literals lbls, unsigned idx) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_disable_literal(c, lbls, idx);
|
||||
RESET_ERROR_CODE();
|
||||
(*reinterpret_cast<labels*>(lbls))[idx].disable();
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_block_literals(Z3_context c, Z3_literals lbls) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_block_literals(c, lbls);
|
||||
RESET_ERROR_CODE();
|
||||
labels* _lbls = reinterpret_cast<labels*>(lbls);
|
||||
ast_manager& m = mk_c(c)->m();
|
||||
expr_ref_vector lits(m);
|
||||
for (unsigned i = 0; i < _lbls->size(); ++i) {
|
||||
if ((*_lbls)[i].is_enabled()) {
|
||||
lits.push_back(m.mk_not((*_lbls)[i].get_literal()));
|
||||
}
|
||||
}
|
||||
expr_ref clause(m);
|
||||
clause = m.mk_or(lits.size(), lits.c_ptr());
|
||||
mk_c(c)->save_ast_trail(clause.get());
|
||||
mk_c(c)->assert_cnstr(clause.get());
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
char const * Z3_API Z3_context_to_string(Z3_context c) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_context_to_string(c);
|
||||
RESET_ERROR_CODE();
|
||||
std::ostringstream buffer;
|
||||
mk_c(c)->get_solver().display(buffer);
|
||||
return mk_c(c)->mk_external_string(buffer.str());
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_get_context_assignment(Z3_context c) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_context_assignment(c);
|
||||
RESET_ERROR_CODE();
|
||||
ast_manager& m = mk_c(c)->m();
|
||||
expr_ref result(m);
|
||||
expr_ref_vector assignment(m);
|
||||
mk_c(c)->get_solver().get_assignments(assignment);
|
||||
result = mk_c(c)->mk_and(assignment.size(), assignment.c_ptr());
|
||||
RETURN_Z3(of_ast(result.get()));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_string Z3_API Z3_statistics_to_string(Z3_context c) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_statistics_to_string(c);
|
||||
RESET_ERROR_CODE();
|
||||
std::ostringstream buffer;
|
||||
mk_c(c)->get_solver().display_statistics(buffer);
|
||||
memory::display_max_usage(buffer);
|
||||
return mk_c(c)->mk_external_string(buffer.str());
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
void Z3_API Z3_soft_check_cancel(Z3_context c) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_soft_check_cancel(c);
|
||||
RESET_ERROR_CODE();
|
||||
mk_c(c)->interrupt();
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
void Z3_display_statistics(Z3_context c, std::ostream& s) {
|
||||
mk_c(c)->get_solver().display_statistics(s);
|
||||
}
|
||||
|
||||
void Z3_display_istatistics(Z3_context c, std::ostream& s) {
|
||||
mk_c(c)->get_solver().display_istatistics(s);
|
||||
}
|
||||
|
133
lib/api_stats.cpp
Normal file
133
lib/api_stats.cpp
Normal file
|
@ -0,0 +1,133 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
api_stats.cpp
|
||||
|
||||
Abstract:
|
||||
API for browsing statistics
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2012-03-07.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include<iostream>
|
||||
#include"z3.h"
|
||||
#include"api_log_macros.h"
|
||||
#include"api_context.h"
|
||||
#include"api_stats.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
Z3_string Z3_API Z3_stats_to_string(Z3_context c, Z3_stats s) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_stats_to_string(c, s);
|
||||
RESET_ERROR_CODE();
|
||||
std::ostringstream buffer;
|
||||
to_stats_ref(s).display_smt2(buffer);
|
||||
std::string result = buffer.str();
|
||||
// Hack for removing the trailing '\n'
|
||||
result = buffer.str();
|
||||
SASSERT(result.size() > 0);
|
||||
result.resize(result.size()-1);
|
||||
return mk_c(c)->mk_external_string(result);
|
||||
Z3_CATCH_RETURN("");
|
||||
}
|
||||
|
||||
void Z3_API Z3_stats_inc_ref(Z3_context c, Z3_stats s) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_stats_inc_ref(c, s);
|
||||
RESET_ERROR_CODE();
|
||||
to_stats(s)->inc_ref();
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_stats_dec_ref(Z3_context c, Z3_stats s) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_stats_dec_ref(c, s);
|
||||
RESET_ERROR_CODE();
|
||||
to_stats(s)->dec_ref();
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
unsigned Z3_API Z3_stats_size(Z3_context c, Z3_stats s) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_stats_size(c, s);
|
||||
RESET_ERROR_CODE();
|
||||
return to_stats_ref(s).size();
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_string Z3_API Z3_stats_get_key(Z3_context c, Z3_stats s, unsigned idx) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_stats_get_key(c, s, idx);
|
||||
RESET_ERROR_CODE();
|
||||
if (idx >= to_stats_ref(s).size()) {
|
||||
SET_ERROR_CODE(Z3_IOB);
|
||||
return "";
|
||||
}
|
||||
return to_stats_ref(s).get_key(idx);
|
||||
Z3_CATCH_RETURN("");
|
||||
}
|
||||
|
||||
Z3_bool Z3_API Z3_stats_is_uint(Z3_context c, Z3_stats s, unsigned idx) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_stats_is_uint(c, s, idx);
|
||||
RESET_ERROR_CODE();
|
||||
if (idx >= to_stats_ref(s).size()) {
|
||||
SET_ERROR_CODE(Z3_IOB);
|
||||
return Z3_FALSE;
|
||||
}
|
||||
return to_stats_ref(s).is_uint(idx);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_bool Z3_API Z3_stats_is_double(Z3_context c, Z3_stats s, unsigned idx) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_stats_is_double(c, s, idx);
|
||||
RESET_ERROR_CODE();
|
||||
if (idx >= to_stats_ref(s).size()) {
|
||||
SET_ERROR_CODE(Z3_IOB);
|
||||
return Z3_FALSE;
|
||||
}
|
||||
return !to_stats_ref(s).is_uint(idx);
|
||||
Z3_CATCH_RETURN(Z3_FALSE);
|
||||
}
|
||||
|
||||
unsigned Z3_API Z3_stats_get_uint_value(Z3_context c, Z3_stats s, unsigned idx) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_stats_get_uint_value(c, s, idx);
|
||||
RESET_ERROR_CODE();
|
||||
if (idx >= to_stats_ref(s).size()) {
|
||||
SET_ERROR_CODE(Z3_IOB);
|
||||
return 0;
|
||||
}
|
||||
if (!to_stats_ref(s).is_uint(idx)) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
return 0;
|
||||
}
|
||||
return to_stats_ref(s).get_uint_value(idx);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
double Z3_API Z3_stats_get_double_value(Z3_context c, Z3_stats s, unsigned idx) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_stats_get_double_value(c, s, idx);
|
||||
RESET_ERROR_CODE();
|
||||
if (idx >= to_stats_ref(s).size()) {
|
||||
SET_ERROR_CODE(Z3_IOB);
|
||||
return 0.0;
|
||||
}
|
||||
if (to_stats_ref(s).is_uint(idx)) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
return 0.0;
|
||||
}
|
||||
return to_stats_ref(s).get_double_value(idx);
|
||||
Z3_CATCH_RETURN(0.0);
|
||||
}
|
||||
|
||||
};
|
33
lib/api_stats.h
Normal file
33
lib/api_stats.h
Normal file
|
@ -0,0 +1,33 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
api_stats.h
|
||||
|
||||
Abstract:
|
||||
API for Z3 statistics
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2012-03-07.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _API_STATS_H_
|
||||
#define _API_STATS_H_
|
||||
|
||||
#include"api_util.h"
|
||||
#include"statistics.h"
|
||||
|
||||
struct Z3_stats_ref : public api::object {
|
||||
statistics m_stats;
|
||||
virtual ~Z3_stats_ref() {}
|
||||
};
|
||||
|
||||
inline Z3_stats_ref * to_stats(Z3_stats s) { return reinterpret_cast<Z3_stats_ref *>(s); }
|
||||
inline Z3_stats of_stats(Z3_stats_ref * s) { return reinterpret_cast<Z3_stats>(s); }
|
||||
inline statistics & to_stats_ref(Z3_stats s) { return to_stats(s)->m_stats; }
|
||||
|
||||
#endif
|
528
lib/api_tactic.cpp
Normal file
528
lib/api_tactic.cpp
Normal file
|
@ -0,0 +1,528 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
api_tactic.cpp
|
||||
|
||||
Abstract:
|
||||
API for creating tactics and probes
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2012-03-06.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include<iostream>
|
||||
#include"z3.h"
|
||||
#include"api_log_macros.h"
|
||||
#include"api_context.h"
|
||||
#include"api_tactic.h"
|
||||
#include"api_model.h"
|
||||
#include"scoped_ctrl_c.h"
|
||||
#include"cancel_eh.h"
|
||||
#include"scoped_timer.h"
|
||||
|
||||
Z3_apply_result_ref::Z3_apply_result_ref(ast_manager & m):m_core(m) {
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
#define RETURN_TACTIC(_t_) { \
|
||||
Z3_tactic_ref * _ref_ = alloc(Z3_tactic_ref); \
|
||||
_ref_->m_tactic = _t_; \
|
||||
mk_c(c)->save_object(_ref_); \
|
||||
Z3_tactic _result_ = of_tactic(_ref_); \
|
||||
RETURN_Z3(_result_); \
|
||||
}
|
||||
|
||||
#define RETURN_PROBE(_t_) { \
|
||||
Z3_probe_ref * _ref_ = alloc(Z3_probe_ref); \
|
||||
_ref_->m_probe = _t_; \
|
||||
mk_c(c)->save_object(_ref_); \
|
||||
Z3_probe _result_ = of_probe(_ref_); \
|
||||
RETURN_Z3(_result_); \
|
||||
}
|
||||
|
||||
Z3_tactic Z3_API Z3_mk_tactic(Z3_context c, Z3_string name) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_tactic(c, name);
|
||||
RESET_ERROR_CODE();
|
||||
tactic_cmd * t = mk_c(c)->find_tactic_cmd(symbol(name));
|
||||
if (t == 0) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
tactic * new_t = t->mk(mk_c(c)->m());
|
||||
RETURN_TACTIC(new_t);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
void Z3_API Z3_tactic_inc_ref(Z3_context c, Z3_tactic t) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_tactic_inc_ref(c, t);
|
||||
RESET_ERROR_CODE();
|
||||
to_tactic(t)->inc_ref();
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_tactic_dec_ref(Z3_context c, Z3_tactic t) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_tactic_dec_ref(c, t);
|
||||
RESET_ERROR_CODE();
|
||||
to_tactic(t)->dec_ref();
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
Z3_probe Z3_API Z3_mk_probe(Z3_context c, Z3_string name) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_probe(c, name);
|
||||
RESET_ERROR_CODE();
|
||||
probe_info * p = mk_c(c)->find_probe(symbol(name));
|
||||
if (p == 0) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
probe * new_p = p->get();
|
||||
RETURN_PROBE(new_p);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
void Z3_API Z3_probe_inc_ref(Z3_context c, Z3_probe p) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_probe_inc_ref(c, p);
|
||||
RESET_ERROR_CODE();
|
||||
to_probe(p)->inc_ref();
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_probe_dec_ref(Z3_context c, Z3_probe p) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_probe_dec_ref(c, p);
|
||||
RESET_ERROR_CODE();
|
||||
to_probe(p)->dec_ref();
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
Z3_tactic Z3_API Z3_tactic_and_then(Z3_context c, Z3_tactic t1, Z3_tactic t2) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_tactic_and_then(c, t1, t2);
|
||||
RESET_ERROR_CODE();
|
||||
tactic * new_t = and_then(to_tactic_ref(t1), to_tactic_ref(t2));
|
||||
RETURN_TACTIC(new_t);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_tactic Z3_API Z3_tactic_or_else(Z3_context c, Z3_tactic t1, Z3_tactic t2) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_tactic_or_else(c, t1, t2);
|
||||
RESET_ERROR_CODE();
|
||||
tactic * new_t = or_else(to_tactic_ref(t1), to_tactic_ref(t2));
|
||||
RETURN_TACTIC(new_t);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_tactic Z3_API Z3_tactic_par_or(Z3_context c, unsigned num, Z3_tactic const ts[]) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_tactic_par_or(c, num, ts);
|
||||
RESET_ERROR_CODE();
|
||||
ptr_buffer<tactic> _ts;
|
||||
for (unsigned i = 0; i < num; i++) {
|
||||
_ts.push_back(to_tactic_ref(ts[i]));
|
||||
}
|
||||
tactic * new_t = par(num, _ts.c_ptr());
|
||||
RETURN_TACTIC(new_t);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_tactic Z3_API Z3_tactic_par_and_then(Z3_context c, Z3_tactic t1, Z3_tactic t2) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_tactic_par_and_then(c, t1, t2);
|
||||
RESET_ERROR_CODE();
|
||||
tactic * new_t = par_and_then(to_tactic_ref(t1), to_tactic_ref(t2));
|
||||
RETURN_TACTIC(new_t);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_tactic Z3_API Z3_tactic_try_for(Z3_context c, Z3_tactic t, unsigned ms) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_tactic_try_for(c, t, ms);
|
||||
RESET_ERROR_CODE();
|
||||
tactic * new_t = try_for(to_tactic_ref(t), ms);
|
||||
RETURN_TACTIC(new_t);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_tactic Z3_API Z3_tactic_when(Z3_context c, Z3_probe p, Z3_tactic t) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_tactic_when(c, p, t);
|
||||
RESET_ERROR_CODE();
|
||||
tactic * new_t = when(to_probe_ref(p), to_tactic_ref(t));
|
||||
RETURN_TACTIC(new_t);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_tactic Z3_API Z3_tactic_cond(Z3_context c, Z3_probe p, Z3_tactic t1, Z3_tactic t2) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_tactic_cond(c, p, t1, t2);
|
||||
RESET_ERROR_CODE();
|
||||
tactic * new_t = cond(to_probe_ref(p), to_tactic_ref(t1), to_tactic_ref(t2));
|
||||
RETURN_TACTIC(new_t);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_tactic Z3_API Z3_tactic_repeat(Z3_context c, Z3_tactic t, unsigned max) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_tactic_repeat(c, t, max);
|
||||
RESET_ERROR_CODE();
|
||||
tactic * new_t = repeat(to_tactic_ref(t), max);
|
||||
RETURN_TACTIC(new_t);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_tactic Z3_API Z3_tactic_skip(Z3_context c) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_tactic_skip(c);
|
||||
RESET_ERROR_CODE();
|
||||
tactic * new_t = mk_skip_tactic();
|
||||
RETURN_TACTIC(new_t);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_tactic Z3_API Z3_tactic_fail(Z3_context c) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_tactic_fail(c);
|
||||
RESET_ERROR_CODE();
|
||||
tactic * new_t = mk_fail_tactic();
|
||||
RETURN_TACTIC(new_t);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_tactic Z3_API Z3_tactic_fail_if(Z3_context c, Z3_probe p) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_tactic_fail_if(c, p);
|
||||
RESET_ERROR_CODE();
|
||||
tactic * new_t = fail_if(to_probe_ref(p));
|
||||
RETURN_TACTIC(new_t);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_tactic Z3_API Z3_tactic_fail_if_not_decided(Z3_context c) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_tactic_fail_if_not_decided(c);
|
||||
RESET_ERROR_CODE();
|
||||
tactic * new_t = mk_fail_if_undecided_tactic();
|
||||
RETURN_TACTIC(new_t);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_tactic Z3_API Z3_tactic_using_params(Z3_context c, Z3_tactic t, Z3_params p) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_tactic_using_params(c, t, p);
|
||||
RESET_ERROR_CODE();
|
||||
tactic * new_t = using_params(to_tactic_ref(t), to_param_ref(p));
|
||||
RETURN_TACTIC(new_t);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_probe Z3_API Z3_probe_const(Z3_context c, double val) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_probe_const(c, val);
|
||||
RESET_ERROR_CODE();
|
||||
probe * new_p = mk_const_probe(val);
|
||||
RETURN_PROBE(new_p);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_probe Z3_API Z3_probe_lt(Z3_context c, Z3_probe p1, Z3_probe p2) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_probe_lt(c, p1, p2);
|
||||
RESET_ERROR_CODE();
|
||||
probe * new_p = mk_lt(to_probe_ref(p1), to_probe_ref(p2));
|
||||
RETURN_PROBE(new_p);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_probe Z3_API Z3_probe_gt(Z3_context c, Z3_probe p1, Z3_probe p2) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_probe_gt(c, p1, p2);
|
||||
RESET_ERROR_CODE();
|
||||
probe * new_p = mk_gt(to_probe_ref(p1), to_probe_ref(p2));
|
||||
RETURN_PROBE(new_p);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_probe Z3_API Z3_probe_le(Z3_context c, Z3_probe p1, Z3_probe p2) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_probe_le(c, p1, p2);
|
||||
RESET_ERROR_CODE();
|
||||
probe * new_p = mk_le(to_probe_ref(p1), to_probe_ref(p2));
|
||||
RETURN_PROBE(new_p);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_probe Z3_API Z3_probe_ge(Z3_context c, Z3_probe p1, Z3_probe p2) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_probe_ge(c, p1, p2);
|
||||
RESET_ERROR_CODE();
|
||||
probe * new_p = mk_ge(to_probe_ref(p1), to_probe_ref(p2));
|
||||
RETURN_PROBE(new_p);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_probe Z3_API Z3_probe_eq(Z3_context c, Z3_probe p1, Z3_probe p2) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_probe_eq(c, p1, p2);
|
||||
RESET_ERROR_CODE();
|
||||
probe * new_p = mk_eq(to_probe_ref(p1), to_probe_ref(p2));
|
||||
RETURN_PROBE(new_p);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_probe Z3_API Z3_probe_and(Z3_context c, Z3_probe p1, Z3_probe p2) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_probe_and(c, p1, p2);
|
||||
RESET_ERROR_CODE();
|
||||
probe * new_p = mk_and(to_probe_ref(p1), to_probe_ref(p2));
|
||||
RETURN_PROBE(new_p);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_probe Z3_API Z3_probe_or(Z3_context c, Z3_probe p1, Z3_probe p2) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_probe_or(c, p1, p2);
|
||||
RESET_ERROR_CODE();
|
||||
probe * new_p = mk_or(to_probe_ref(p1), to_probe_ref(p2));
|
||||
RETURN_PROBE(new_p);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_probe Z3_API Z3_probe_not(Z3_context c, Z3_probe p) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_probe_not(c, p);
|
||||
RESET_ERROR_CODE();
|
||||
probe * new_p = mk_not(to_probe_ref(p));
|
||||
RETURN_PROBE(new_p);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
unsigned Z3_API Z3_get_num_tactics(Z3_context c) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_num_tactics(c);
|
||||
RESET_ERROR_CODE();
|
||||
return mk_c(c)->num_tactics();
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_string Z3_API Z3_get_tactic_name(Z3_context c, unsigned idx) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_tactic_name(c, idx);
|
||||
RESET_ERROR_CODE();
|
||||
if (idx >= mk_c(c)->num_tactics()) {
|
||||
SET_ERROR_CODE(Z3_IOB);
|
||||
return "";
|
||||
}
|
||||
return mk_c(c)->get_tactic(idx)->get_name().bare_str();
|
||||
Z3_CATCH_RETURN("");
|
||||
}
|
||||
|
||||
unsigned Z3_API Z3_get_num_probes(Z3_context c) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_num_probes(c);
|
||||
RESET_ERROR_CODE();
|
||||
return mk_c(c)->num_probes();
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_string Z3_API Z3_get_probe_name(Z3_context c, unsigned idx) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_probe_name(c, idx);
|
||||
RESET_ERROR_CODE();
|
||||
if (idx >= mk_c(c)->num_probes()) {
|
||||
SET_ERROR_CODE(Z3_IOB);
|
||||
return "";
|
||||
}
|
||||
return mk_c(c)->get_probe(idx)->get_name().bare_str();
|
||||
Z3_CATCH_RETURN("");
|
||||
}
|
||||
|
||||
Z3_string Z3_API Z3_tactic_get_help(Z3_context c, Z3_tactic t) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_tactic_get_help(c, t);
|
||||
RESET_ERROR_CODE();
|
||||
std::ostringstream buffer;
|
||||
param_descrs descrs;
|
||||
to_tactic_ref(t)->collect_param_descrs(descrs);
|
||||
descrs.display(buffer);
|
||||
return mk_c(c)->mk_external_string(buffer.str());
|
||||
Z3_CATCH_RETURN("");
|
||||
}
|
||||
|
||||
Z3_param_descrs Z3_API Z3_tactic_get_param_descrs(Z3_context c, Z3_tactic t) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_tactic_get_param_descrs(c, t);
|
||||
RESET_ERROR_CODE();
|
||||
Z3_param_descrs_ref * d = alloc(Z3_param_descrs_ref);
|
||||
mk_c(c)->save_object(d);
|
||||
to_tactic_ref(t)->collect_param_descrs(d->m_descrs);
|
||||
Z3_param_descrs r = of_param_descrs(d);
|
||||
RETURN_Z3(r);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_string Z3_API Z3_tactic_get_descr(Z3_context c, Z3_string name) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_tactic_get_descr(c, name);
|
||||
RESET_ERROR_CODE();
|
||||
tactic_cmd * t = mk_c(c)->find_tactic_cmd(symbol(name));
|
||||
if (t == 0) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
return "";
|
||||
}
|
||||
return t->get_descr();
|
||||
Z3_CATCH_RETURN("");
|
||||
}
|
||||
|
||||
Z3_string Z3_API Z3_probe_get_descr(Z3_context c, Z3_string name) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_probe_get_descr(c, name);
|
||||
RESET_ERROR_CODE();
|
||||
probe_info * p = mk_c(c)->find_probe(symbol(name));
|
||||
if (p == 0) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
return "";
|
||||
}
|
||||
return p->get_descr();
|
||||
Z3_CATCH_RETURN("");
|
||||
}
|
||||
|
||||
static Z3_apply_result _tactic_apply(Z3_context c, Z3_tactic t, Z3_goal g, params_ref p) {
|
||||
goal_ref new_goal;
|
||||
new_goal = alloc(goal, *to_goal_ref(g));
|
||||
Z3_apply_result_ref * ref = alloc(Z3_apply_result_ref, mk_c(c)->m());
|
||||
mk_c(c)->save_object(ref);
|
||||
|
||||
unsigned timeout = p.get_uint(":timeout", UINT_MAX);
|
||||
bool use_ctrl_c = p.get_bool(":ctrl-c", false);
|
||||
cancel_eh<tactic> eh(*to_tactic_ref(t));
|
||||
|
||||
to_tactic_ref(t)->updt_params(p);
|
||||
|
||||
api::context::set_interruptable(*(mk_c(c)), eh);
|
||||
{
|
||||
scoped_ctrl_c ctrlc(eh, false, use_ctrl_c);
|
||||
scoped_timer timer(timeout, &eh);
|
||||
try {
|
||||
exec(*to_tactic_ref(t), new_goal, ref->m_subgoals, ref->m_mc, ref->m_pc, ref->m_core);
|
||||
return of_apply_result(ref);
|
||||
}
|
||||
catch (z3_exception & ex) {
|
||||
mk_c(c)->handle_exception(ex);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
double Z3_API Z3_probe_apply(Z3_context c, Z3_probe p, Z3_goal g) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_probe_apply(c, p, g);
|
||||
RESET_ERROR_CODE();
|
||||
return to_probe_ref(p)->operator()(*to_goal_ref(g)).get_value();
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_apply_result Z3_API Z3_tactic_apply(Z3_context c, Z3_tactic t, Z3_goal g) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_tactic_apply(c, t, g);
|
||||
RESET_ERROR_CODE();
|
||||
params_ref p;
|
||||
Z3_apply_result r = _tactic_apply(c, t, g, p);
|
||||
RETURN_Z3(r);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_apply_result Z3_API Z3_tactic_apply_ex(Z3_context c, Z3_tactic t, Z3_goal g, Z3_params p) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_tactic_apply_ex(c, t, g, p);
|
||||
RESET_ERROR_CODE();
|
||||
Z3_apply_result r = _tactic_apply(c, t, g, to_param_ref(p));
|
||||
RETURN_Z3(r);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
void Z3_API Z3_apply_result_inc_ref(Z3_context c, Z3_apply_result r) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_apply_result_inc_ref(c, r);
|
||||
RESET_ERROR_CODE();
|
||||
to_apply_result(r)->inc_ref();
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_apply_result_dec_ref(Z3_context c, Z3_apply_result r) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_apply_result_dec_ref(c, r);
|
||||
RESET_ERROR_CODE();
|
||||
to_apply_result(r)->dec_ref();
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
Z3_string Z3_API Z3_apply_result_to_string(Z3_context c, Z3_apply_result r) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_apply_result_to_string(c, r);
|
||||
RESET_ERROR_CODE();
|
||||
std::ostringstream buffer;
|
||||
buffer << "(goals\n";
|
||||
unsigned sz = to_apply_result(r)->m_subgoals.size();
|
||||
for (unsigned i = 0; i < sz; i++) {
|
||||
to_apply_result(r)->m_subgoals[i]->display(buffer);
|
||||
}
|
||||
buffer << ")";
|
||||
return mk_c(c)->mk_external_string(buffer.str());
|
||||
Z3_CATCH_RETURN("");
|
||||
}
|
||||
|
||||
unsigned Z3_API Z3_apply_result_get_num_subgoals(Z3_context c, Z3_apply_result r) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_apply_result_get_num_subgoals(c, r);
|
||||
RESET_ERROR_CODE();
|
||||
return to_apply_result(r)->m_subgoals.size();
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_goal Z3_API Z3_apply_result_get_subgoal(Z3_context c, Z3_apply_result r, unsigned i) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_apply_result_get_subgoal(c, r, i);
|
||||
RESET_ERROR_CODE();
|
||||
if (i > to_apply_result(r)->m_subgoals.size()) {
|
||||
SET_ERROR_CODE(Z3_IOB);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
Z3_goal_ref * g = alloc(Z3_goal_ref);
|
||||
g->m_goal = to_apply_result(r)->m_subgoals[i];
|
||||
mk_c(c)->save_object(g);
|
||||
Z3_goal result = of_goal(g);
|
||||
RETURN_Z3(result);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_model Z3_API Z3_apply_result_convert_model(Z3_context c, Z3_apply_result r, unsigned i, Z3_model m) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_apply_result_convert_model(c, r, i, m);
|
||||
RESET_ERROR_CODE();
|
||||
if (i > to_apply_result(r)->m_subgoals.size()) {
|
||||
SET_ERROR_CODE(Z3_IOB);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
model_ref new_m = to_model_ref(m)->copy();
|
||||
if (to_apply_result(r)->m_mc)
|
||||
to_apply_result(r)->m_mc->operator()(new_m, i);
|
||||
Z3_model_ref * m_ref = alloc(Z3_model_ref);
|
||||
m_ref->m_model = new_m;
|
||||
mk_c(c)->save_object(m_ref);
|
||||
RETURN_Z3(of_model(m_ref));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
};
|
54
lib/api_tactic.h
Normal file
54
lib/api_tactic.h
Normal file
|
@ -0,0 +1,54 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
api_tactic.h
|
||||
|
||||
Abstract:
|
||||
API for creating tactics and goals.
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2012-03-06.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _API_TACTIC_H_
|
||||
#define _API_TACTIC_H_
|
||||
|
||||
#include"api_goal.h"
|
||||
#include"tactical.h"
|
||||
|
||||
struct Z3_tactic_ref : public api::object {
|
||||
tactic_ref m_tactic;
|
||||
virtual ~Z3_tactic_ref() {}
|
||||
};
|
||||
|
||||
struct Z3_probe_ref : public api::object {
|
||||
probe_ref m_probe;
|
||||
virtual ~Z3_probe_ref() {}
|
||||
};
|
||||
|
||||
inline Z3_tactic_ref * to_tactic(Z3_tactic g) { return reinterpret_cast<Z3_tactic_ref *>(g); }
|
||||
inline Z3_tactic of_tactic(Z3_tactic_ref * g) { return reinterpret_cast<Z3_tactic>(g); }
|
||||
inline tactic * to_tactic_ref(Z3_tactic g) { return g == 0 ? 0 : to_tactic(g)->m_tactic.get(); }
|
||||
|
||||
inline Z3_probe_ref * to_probe(Z3_probe g) { return reinterpret_cast<Z3_probe_ref *>(g); }
|
||||
inline Z3_probe of_probe(Z3_probe_ref * g) { return reinterpret_cast<Z3_probe>(g); }
|
||||
inline probe * to_probe_ref(Z3_probe g) { return g == 0 ? 0 : to_probe(g)->m_probe.get(); }
|
||||
|
||||
struct Z3_apply_result_ref : public api::object {
|
||||
goal_ref_buffer m_subgoals;
|
||||
model_converter_ref m_mc;
|
||||
proof_converter_ref m_pc;
|
||||
expr_dependency_ref m_core;
|
||||
Z3_apply_result_ref(ast_manager & m);
|
||||
virtual ~Z3_apply_result_ref() {}
|
||||
};
|
||||
|
||||
inline Z3_apply_result_ref * to_apply_result(Z3_apply_result g) { return reinterpret_cast<Z3_apply_result_ref *>(g); }
|
||||
inline Z3_apply_result of_apply_result(Z3_apply_result_ref * g) { return reinterpret_cast<Z3_apply_result>(g); }
|
||||
|
||||
#endif
|
333
lib/api_user_theory.cpp
Normal file
333
lib/api_user_theory.cpp
Normal file
|
@ -0,0 +1,333 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
api_user_theory.cpp
|
||||
|
||||
Abstract:
|
||||
API for external theories
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2012-02-29.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include<iostream>
|
||||
#include"z3.h"
|
||||
#include"api_log_macros.h"
|
||||
#include"api_context.h"
|
||||
#include"api_util.h"
|
||||
#include"user_smt_theory.h"
|
||||
|
||||
smt::user_theory * mk_t(Z3_theory t) {
|
||||
return reinterpret_cast<smt::user_theory*>(t);
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
///////////////////////////////
|
||||
// Theory plugin
|
||||
// No support for logging
|
||||
|
||||
Z3_theory Z3_mk_theory(Z3_context c, Z3_string th_name, void * ext_data) {
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
if (mk_c(c)->get_solver().get_scope_level() > 0) {
|
||||
SET_ERROR_CODE(Z3_INVALID_USAGE);
|
||||
return 0;
|
||||
}
|
||||
return reinterpret_cast<Z3_theory>(mk_user_theory(mk_c(c)->get_solver(), c, ext_data, th_name));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
void * Z3_theory_get_ext_data(Z3_theory t) {
|
||||
Z3_context c = Z3_theory_get_context(t);
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
void * r = mk_t(t)->get_ext_data();
|
||||
return r;
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_sort Z3_theory_mk_sort(Z3_context c, Z3_theory t, Z3_symbol s) {
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
sort * r = mk_t(t)->mk_sort(to_symbol(s));
|
||||
mk_c(c)->save_ast_trail(r);
|
||||
return of_sort(r);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_theory_mk_value(Z3_context c, Z3_theory t, Z3_symbol n, Z3_sort s) {
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
func_decl * d = mk_t(t)->mk_value_decl(to_symbol(n), to_sort(s));
|
||||
app * r = mk_c(c)->m().mk_const(d);
|
||||
mk_c(c)->save_ast_trail(r);
|
||||
return of_ast(r);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_theory_mk_constant(Z3_context c, Z3_theory t, Z3_symbol n, Z3_sort s) {
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
Z3_func_decl d = Z3_theory_mk_func_decl(c, t, n, 0, 0, s);
|
||||
app * r = mk_c(c)->m().mk_const(to_func_decl(d));
|
||||
mk_c(c)->save_ast_trail(r);
|
||||
return of_ast(r);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_func_decl Z3_theory_mk_func_decl(Z3_context c, Z3_theory t, Z3_symbol n,
|
||||
unsigned domain_size, Z3_sort const domain[],
|
||||
Z3_sort range) {
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
func_decl * r = mk_t(t)->mk_func_decl(to_symbol(n), domain_size, to_sorts(domain), to_sort(range));
|
||||
mk_c(c)->save_ast_trail(r);
|
||||
return of_func_decl(r);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_context Z3_theory_get_context(Z3_theory t) {
|
||||
Z3_context c = reinterpret_cast<Z3_context>(mk_t(t)->get_ext_context());
|
||||
RESET_ERROR_CODE();
|
||||
return c;
|
||||
}
|
||||
|
||||
void Z3_set_delete_callback(Z3_theory t, Z3_theory_callback_fptr f) {
|
||||
Z3_context c = Z3_theory_get_context(t);
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
mk_t(t)->set_delete_fptr(reinterpret_cast<smt::theory_callback_fptr>(f));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_set_reduce_app_callback(Z3_theory t, Z3_reduce_app_callback_fptr f) {
|
||||
Z3_context c = Z3_theory_get_context(t);
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
mk_t(t)->set_reduce_app_fptr(reinterpret_cast<reduce_app_fptr>(f));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_set_reduce_eq_callback(Z3_theory t, Z3_reduce_eq_callback_fptr f) {
|
||||
Z3_context c = Z3_theory_get_context(t);
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
mk_t(t)->set_reduce_eq_fptr(reinterpret_cast<reduce_eq_fptr>(f));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_set_reduce_distinct_callback(Z3_theory t, Z3_reduce_distinct_callback_fptr f) {
|
||||
Z3_context c = Z3_theory_get_context(t);
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
mk_t(t)->set_reduce_distinct_fptr(reinterpret_cast<reduce_distinct_fptr>(f));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_set_new_app_callback(Z3_theory t, Z3_theory_ast_callback_fptr f) {
|
||||
Z3_context c = Z3_theory_get_context(t);
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
mk_t(t)->set_new_app_fptr(reinterpret_cast<smt::theory_app_callback_fptr>(f));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_set_new_elem_callback(Z3_theory t, Z3_theory_ast_callback_fptr f) {
|
||||
Z3_context c = Z3_theory_get_context(t);
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
mk_t(t)->set_new_elem_fptr(reinterpret_cast<smt::theory_app_callback_fptr>(f));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_set_init_search_callback(Z3_theory t, Z3_theory_callback_fptr f) {
|
||||
Z3_context c = Z3_theory_get_context(t);
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
mk_t(t)->set_init_search_fptr(reinterpret_cast<smt::theory_callback_fptr>(f));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_set_push_callback(Z3_theory t, Z3_theory_callback_fptr f) {
|
||||
Z3_context c = Z3_theory_get_context(t);
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
mk_t(t)->set_push_fptr(reinterpret_cast<smt::theory_callback_fptr>(f));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_set_pop_callback(Z3_theory t, Z3_theory_callback_fptr f) {
|
||||
Z3_context c = Z3_theory_get_context(t);
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
mk_t(t)->set_pop_fptr(reinterpret_cast<smt::theory_callback_fptr>(f));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_set_restart_callback(Z3_theory t, Z3_theory_callback_fptr f) {
|
||||
Z3_context c = Z3_theory_get_context(t);
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
mk_t(t)->set_restart_fptr(reinterpret_cast<smt::theory_callback_fptr>(f));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_set_reset_callback(Z3_theory t, Z3_theory_callback_fptr f) {
|
||||
Z3_context c = Z3_theory_get_context(t);
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
mk_t(t)->set_reset_fptr(reinterpret_cast<smt::theory_callback_fptr>(f));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_set_final_check_callback(Z3_theory t, Z3_theory_final_check_callback_fptr f) {
|
||||
Z3_context c = Z3_theory_get_context(t);
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
mk_t(t)->set_final_check_fptr(reinterpret_cast<smt::theory_final_check_callback_fptr>(f));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_set_new_eq_callback(Z3_theory t, Z3_theory_ast_ast_callback_fptr f) {
|
||||
Z3_context c = Z3_theory_get_context(t);
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
mk_t(t)->set_new_eq_fptr(reinterpret_cast<smt::theory_app_app_callback_fptr>(f));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_set_new_diseq_callback(Z3_theory t, Z3_theory_ast_ast_callback_fptr f) {
|
||||
Z3_context c = Z3_theory_get_context(t);
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
mk_t(t)->set_new_diseq_fptr(reinterpret_cast<smt::theory_app_app_callback_fptr>(f));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_set_new_assignment_callback(Z3_theory t, Z3_theory_ast_bool_callback_fptr f) {
|
||||
Z3_context c = Z3_theory_get_context(t);
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
mk_t(t)->set_new_assignment_fptr(reinterpret_cast<smt::theory_app_bool_callback_fptr>(f));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_set_new_relevant_callback(Z3_theory t, Z3_theory_ast_callback_fptr f) {
|
||||
Z3_context c = Z3_theory_get_context(t);
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
mk_t(t)->set_new_relevant_fptr(reinterpret_cast<smt::theory_app_callback_fptr>(f));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_theory_assert_axiom(Z3_theory t, Z3_ast ax) {
|
||||
Z3_context c = Z3_theory_get_context(t);
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
mk_t(t)->assert_axiom(to_ast(ax));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_theory_assume_eq(Z3_theory t, Z3_ast lhs, Z3_ast rhs) {
|
||||
Z3_context c = Z3_theory_get_context(t);
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
mk_t(t)->assume_eq(to_ast(lhs), to_ast(rhs));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_theory_enable_axiom_simplification(Z3_theory t, Z3_bool flag) {
|
||||
Z3_context c = Z3_theory_get_context(t);
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
mk_t(t)->enable_axiom_simplification(flag == Z3_TRUE);
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
Z3_ast Z3_theory_get_eqc_root(Z3_theory t, Z3_ast n) {
|
||||
Z3_context c = Z3_theory_get_context(t);
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
return of_ast(mk_t(t)->get_root(to_ast(n)));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_theory_get_eqc_next(Z3_theory t, Z3_ast n) {
|
||||
Z3_context c = Z3_theory_get_context(t);
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
return of_ast(mk_t(t)->get_next(to_ast(n)));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
unsigned Z3_theory_get_num_parents(Z3_theory t, Z3_ast n) {
|
||||
Z3_context c = Z3_theory_get_context(t);
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
return mk_t(t)->get_num_parents(to_ast(n));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_theory_get_parent(Z3_theory t, Z3_ast n, unsigned i) {
|
||||
Z3_context c = Z3_theory_get_context(t);
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
return of_ast(mk_t(t)->get_parent(to_ast(n), i));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
unsigned Z3_theory_get_num_elems(Z3_theory t) {
|
||||
Z3_context c = Z3_theory_get_context(t);
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
return mk_t(t)->get_num_asts();
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_theory_get_elem(Z3_theory t, unsigned i) {
|
||||
Z3_context c = Z3_theory_get_context(t);
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
return of_ast(mk_t(t)->get_ast(i));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
unsigned Z3_theory_get_num_apps(Z3_theory t) {
|
||||
Z3_context c = Z3_theory_get_context(t);
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
return mk_t(t)->get_num_parents();
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_theory_get_app(Z3_theory t, unsigned i) {
|
||||
Z3_context c = Z3_theory_get_context(t);
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
return of_ast(mk_t(t)->get_parent(i));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_bool Z3_theory_is_value(Z3_theory t, Z3_ast n) {
|
||||
Z3_context c = Z3_theory_get_context(t);
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
return is_app(to_ast(n)) && mk_t(t)->get_family_id() == to_app(to_ast(n))->get_family_id();
|
||||
Z3_CATCH_RETURN(Z3_FALSE);
|
||||
}
|
||||
|
||||
Z3_bool Z3_theory_is_decl(Z3_theory t, Z3_func_decl d) {
|
||||
Z3_context c = Z3_theory_get_context(t);
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
return mk_t(t)->get_family_id() == to_func_decl(d)->get_family_id();
|
||||
Z3_CATCH_RETURN(Z3_FALSE);
|
||||
}
|
||||
|
||||
};
|
149
lib/api_util.h
Normal file
149
lib/api_util.h
Normal file
|
@ -0,0 +1,149 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
api_util.h
|
||||
|
||||
Abstract:
|
||||
Goodies used to build the Z3 external API.
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2012-02-29.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _API_UTIL_H_
|
||||
#define _API_UTIL_H_
|
||||
|
||||
#include"params.h"
|
||||
#include"lbool.h"
|
||||
|
||||
#define Z3_TRY try {
|
||||
#define Z3_CATCH_CORE(CODE) } catch (z3_exception & ex) { mk_c(c)->handle_exception(ex); CODE }
|
||||
#define Z3_CATCH Z3_CATCH_CORE(return;)
|
||||
#define Z3_CATCH_RETURN(VAL) Z3_CATCH_CORE(return VAL;)
|
||||
|
||||
#define CHECK_REF_COUNT(a) (reinterpret_cast<ast const*>(a)->get_ref_count() > 0)
|
||||
#define VALIDATE(a) SASSERT(!a || CHECK_REF_COUNT(a))
|
||||
|
||||
namespace api {
|
||||
// Generic wrapper for ref-count objects exposed by the API
|
||||
class object {
|
||||
unsigned m_ref_count;
|
||||
public:
|
||||
object():m_ref_count(0) {}
|
||||
virtual ~object() {}
|
||||
void inc_ref() { m_ref_count++; }
|
||||
void dec_ref() { SASSERT(m_ref_count > 0); m_ref_count--; if (m_ref_count == 0) dealloc(this); }
|
||||
};
|
||||
};
|
||||
|
||||
inline ast * to_ast(Z3_ast a) { VALIDATE(a); return reinterpret_cast<ast *>(a); }
|
||||
inline Z3_ast of_ast(ast* a) { return reinterpret_cast<Z3_ast>(a); }
|
||||
|
||||
inline expr * to_expr(Z3_ast a) { VALIDATE(a); return reinterpret_cast<expr*>(a); }
|
||||
inline Z3_ast of_expr(expr* e) { return reinterpret_cast<Z3_ast>(e); }
|
||||
|
||||
inline expr * const * to_exprs(Z3_ast const* a) { return reinterpret_cast<expr* const*>(a); }
|
||||
inline Z3_ast * const * of_exprs(expr* const* e) { return reinterpret_cast<Z3_ast* const*>(e); }
|
||||
|
||||
inline app * to_app(Z3_app a) { VALIDATE(a); return reinterpret_cast<app*>(a); }
|
||||
inline app * to_app(Z3_ast a) { VALIDATE(a); return reinterpret_cast<app*>(a); }
|
||||
inline Z3_app of_app(app* a) { return reinterpret_cast<Z3_app>(a); }
|
||||
|
||||
inline app * const* to_apps(Z3_ast const* a) { VALIDATE(a); return reinterpret_cast<app * const*>(a); }
|
||||
|
||||
inline ast * const * to_asts(Z3_ast const* a) { return reinterpret_cast<ast* const*>(a); }
|
||||
|
||||
inline sort * to_sort(Z3_sort a) { VALIDATE(a); return reinterpret_cast<sort*>(a); }
|
||||
inline Z3_sort of_sort(sort* s) { return reinterpret_cast<Z3_sort>(s); }
|
||||
|
||||
inline sort * const * to_sorts(Z3_sort const* a) { return reinterpret_cast<sort* const*>(a); }
|
||||
inline Z3_sort const * of_sorts(sort* const* s) { return reinterpret_cast<Z3_sort const*>(s); }
|
||||
|
||||
inline func_decl * to_func_decl(Z3_func_decl a) { VALIDATE(a); return reinterpret_cast<func_decl*>(a); }
|
||||
inline Z3_func_decl of_func_decl(func_decl* f) { return reinterpret_cast<Z3_func_decl>(f); }
|
||||
|
||||
inline func_decl * const * to_func_decls(Z3_func_decl const* f) { return reinterpret_cast<func_decl*const*>(f); }
|
||||
|
||||
inline symbol to_symbol(Z3_symbol s) { return symbol::mk_symbol_from_c_ptr(reinterpret_cast<void*>(s)); }
|
||||
inline Z3_symbol of_symbol(symbol s) { return reinterpret_cast<Z3_symbol>(const_cast<void*>(s.c_ptr())); }
|
||||
|
||||
inline Z3_pattern of_pattern(ast* a) { VALIDATE(a); return reinterpret_cast<Z3_pattern>(a); }
|
||||
inline app* to_pattern(Z3_pattern p) { return reinterpret_cast<app*>(p); }
|
||||
|
||||
inline Z3_lbool of_lbool(lbool b) { return static_cast<Z3_lbool>(b); }
|
||||
inline lbool to_lbool(Z3_lbool b) { return static_cast<lbool>(b); }
|
||||
|
||||
struct Z3_params_ref : public api::object {
|
||||
params_ref m_params;
|
||||
virtual ~Z3_params_ref() {}
|
||||
};
|
||||
|
||||
inline Z3_params_ref * to_params(Z3_params p) { return reinterpret_cast<Z3_params_ref *>(p); }
|
||||
inline Z3_params of_params(Z3_params_ref * p) { return reinterpret_cast<Z3_params>(p); }
|
||||
inline params_ref to_param_ref(Z3_params p) { return p == 0 ? params_ref() : to_params(p)->m_params; }
|
||||
|
||||
struct Z3_param_descrs_ref : public api::object {
|
||||
param_descrs m_descrs;
|
||||
virtual ~Z3_param_descrs_ref() {}
|
||||
};
|
||||
|
||||
inline Z3_param_descrs_ref * to_param_descrs(Z3_param_descrs p) { return reinterpret_cast<Z3_param_descrs_ref *>(p); }
|
||||
inline Z3_param_descrs of_param_descrs(Z3_param_descrs_ref * p) { return reinterpret_cast<Z3_param_descrs>(p); }
|
||||
inline param_descrs * to_param_descrs_ptr(Z3_param_descrs p) { return p == 0 ? 0 : &(to_param_descrs(p)->m_descrs); }
|
||||
|
||||
|
||||
#define SKIP ((void) 0)
|
||||
|
||||
#define MK_UNARY_BODY(NAME, FID, OP, EXTRA_CODE) \
|
||||
Z3_TRY; \
|
||||
RESET_ERROR_CODE(); \
|
||||
EXTRA_CODE; \
|
||||
expr * _n = to_expr(n); \
|
||||
ast* a = mk_c(c)->m().mk_app(FID, OP, 0, 0, 1, &_n); \
|
||||
mk_c(c)->save_ast_trail(a); \
|
||||
check_sorts(c, a); \
|
||||
RETURN_Z3(of_ast(a)); \
|
||||
Z3_CATCH_RETURN(0);
|
||||
|
||||
#define MK_UNARY(NAME, FID, OP, EXTRA_CODE) \
|
||||
Z3_ast Z3_API NAME(Z3_context c, Z3_ast n) { \
|
||||
LOG_ ## NAME(c, n); \
|
||||
MK_UNARY_BODY(NAME, FID, OP, EXTRA_CODE); \
|
||||
}
|
||||
|
||||
#define MK_BINARY_BODY(NAME, FID, OP, EXTRA_CODE) \
|
||||
Z3_TRY; \
|
||||
RESET_ERROR_CODE(); \
|
||||
EXTRA_CODE; \
|
||||
expr * args[2] = { to_expr(n1), to_expr(n2) }; \
|
||||
ast* a = mk_c(c)->m().mk_app(FID, OP, 0, 0, 2, args); \
|
||||
mk_c(c)->save_ast_trail(a); \
|
||||
check_sorts(c, a); \
|
||||
RETURN_Z3(of_ast(a)); \
|
||||
Z3_CATCH_RETURN(0);
|
||||
|
||||
#define MK_BINARY(NAME, FID, OP, EXTRA_CODE) \
|
||||
Z3_ast Z3_API NAME(Z3_context c, Z3_ast n1, Z3_ast n2) { \
|
||||
LOG_ ## NAME(c, n1, n2); \
|
||||
MK_BINARY_BODY(NAME, FID, OP, EXTRA_CODE); \
|
||||
}
|
||||
|
||||
#define MK_NARY(NAME, FID, OP, EXTRA_CODE) \
|
||||
Z3_ast Z3_API NAME(Z3_context c, unsigned num_args, Z3_ast const* args) { \
|
||||
Z3_TRY; \
|
||||
LOG_ ## NAME(c, num_args, args); \
|
||||
RESET_ERROR_CODE(); \
|
||||
EXTRA_CODE; \
|
||||
ast* a = mk_c(c)->m().mk_app(FID, OP, 0, 0, num_args, to_exprs(args)); \
|
||||
mk_c(c)->save_ast_trail(a); \
|
||||
check_sorts(c, a); \
|
||||
RETURN_Z3(of_ast(a)); \
|
||||
Z3_CATCH_RETURN(0); \
|
||||
}
|
||||
|
||||
#endif
|
61
lib/approx_nat.cpp
Normal file
61
lib/approx_nat.cpp
Normal file
|
@ -0,0 +1,61 @@
|
|||
/*++
|
||||
Copyright (c) 2007 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
approx_nat.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Approximated natural numbers. It performs operations on the set [0, ..., 2^{n-2}, huge].
|
||||
Where huge represents all numbers greater than 2^{n-2}.
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo (leonardo) 2008-01-11
|
||||
|
||||
Notes:
|
||||
|
||||
--*/
|
||||
#include"approx_nat.h"
|
||||
|
||||
approx_nat::approx_nat(unsigned val) {
|
||||
m_value = val > m_limit ? UINT_MAX : val;
|
||||
}
|
||||
|
||||
approx_nat & approx_nat::operator=(unsigned val) {
|
||||
m_value = val > m_limit ? UINT_MAX : val;
|
||||
return *this;
|
||||
}
|
||||
|
||||
approx_nat & approx_nat::operator+=(unsigned w) {
|
||||
if (is_huge())
|
||||
return *this;
|
||||
if (w > m_limit) {
|
||||
m_value = UINT_MAX;
|
||||
return *this;
|
||||
}
|
||||
m_value += w;
|
||||
if (m_value > m_limit)
|
||||
m_value = UINT_MAX;
|
||||
return *this;
|
||||
}
|
||||
|
||||
approx_nat & approx_nat::operator*=(unsigned w) {
|
||||
if (is_huge())
|
||||
return *this;
|
||||
unsigned long long r = static_cast<unsigned long long>(m_value) * static_cast<unsigned long long>(w);
|
||||
if (r > m_limit)
|
||||
m_value = UINT_MAX;
|
||||
else
|
||||
m_value = static_cast<unsigned>(r);
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::ostream & operator<<(std::ostream & target, approx_nat const & w) {
|
||||
if (w.is_huge())
|
||||
target << "[huge]";
|
||||
else
|
||||
target << w.get_value();
|
||||
return target;
|
||||
}
|
45
lib/approx_nat.h
Normal file
45
lib/approx_nat.h
Normal file
|
@ -0,0 +1,45 @@
|
|||
/*++
|
||||
Copyright (c) 2007 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
approx_nat.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Approximated natural numbers. It performs operations on the set [0, ..., 2^{n-2}, huge].
|
||||
Where huge represents all numbers greater than 2^{n-2}.
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo (leonardo) 2008-01-11
|
||||
|
||||
Notes:
|
||||
|
||||
--*/
|
||||
#ifndef _APPROX_NAT_H_
|
||||
#define _APPROX_NAT_H_
|
||||
|
||||
#include<iostream>
|
||||
#include<limits.h>
|
||||
|
||||
class approx_nat {
|
||||
unsigned m_value;
|
||||
static const unsigned m_limit = UINT_MAX >> 2;
|
||||
public:
|
||||
approx_nat():m_value(0) {}
|
||||
explicit approx_nat(unsigned val);
|
||||
bool is_huge() const { return m_value == UINT_MAX; }
|
||||
unsigned get_value() const { return m_value; }
|
||||
approx_nat & operator=(unsigned w);
|
||||
approx_nat & operator+=(unsigned w);
|
||||
approx_nat & operator+=(approx_nat const & w) { return operator+=(w.m_value); }
|
||||
approx_nat & operator*=(unsigned w);
|
||||
approx_nat & operator*=(approx_nat const & w) { return operator*=(w.m_value); }
|
||||
bool operator<(unsigned w) const { return !is_huge() && m_value < w; }
|
||||
bool operator<(approx_nat const & w) const { return !is_huge() && !w.is_huge() && m_value < w.m_value; }
|
||||
};
|
||||
|
||||
std::ostream & operator<<(std::ostream & target, approx_nat const & w);
|
||||
|
||||
#endif /* _APPROX_NAT_H_ */
|
52
lib/approx_set.cpp
Normal file
52
lib/approx_set.cpp
Normal file
|
@ -0,0 +1,52 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
approx_set.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Approximated sets.
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2007-03-02.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#include"approx_set.h"
|
||||
|
||||
void approx_set::display(std::ostream & out) const {
|
||||
out << "{";
|
||||
bool first = true;
|
||||
unsigned long long s = m_set;
|
||||
for (unsigned i = 0; i < approx_set_traits<unsigned long long>::capacity; i++) {
|
||||
if ((s & 1) != 0) {
|
||||
if (first) {
|
||||
first = false;
|
||||
}
|
||||
else {
|
||||
out << ", ";
|
||||
}
|
||||
out << i;
|
||||
}
|
||||
s = s >> 1;
|
||||
}
|
||||
out << "}";
|
||||
}
|
||||
|
||||
unsigned approx_set::size() const {
|
||||
unsigned long long tmp = m_set;
|
||||
unsigned r = 0;
|
||||
while (tmp > 0) {
|
||||
if ((tmp & 1) != 0) {
|
||||
r++;
|
||||
}
|
||||
tmp = tmp >> 1;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
236
lib/approx_set.h
Normal file
236
lib/approx_set.h
Normal file
|
@ -0,0 +1,236 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
approx_set.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Approximated sets.
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2007-03-02.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _APPROX_SET_H_
|
||||
#define _APPROX_SET_H_
|
||||
#include<iostream>
|
||||
#include"debug.h"
|
||||
|
||||
template<typename T> class approx_set_traits;
|
||||
|
||||
template <> class approx_set_traits<unsigned long long> {
|
||||
public:
|
||||
static const unsigned capacity = 64;
|
||||
static const unsigned long long zero = 0ull;
|
||||
static const unsigned long long one = 1ull;
|
||||
};
|
||||
COMPILE_TIME_ASSERT(sizeof(unsigned long long) == 8);
|
||||
|
||||
template <> class approx_set_traits<unsigned> {
|
||||
public:
|
||||
static const unsigned capacity = 32;
|
||||
static const unsigned zero = 0;
|
||||
static const unsigned one = 1;
|
||||
};
|
||||
COMPILE_TIME_ASSERT(sizeof(unsigned) == 4);
|
||||
|
||||
template<typename T, typename T2U_Proc, typename R=unsigned long long>
|
||||
class approx_set_tpl : private T2U_Proc {
|
||||
protected:
|
||||
R m_set;
|
||||
|
||||
unsigned e2u(T const & e) const { return T2U_Proc::operator()(e); }
|
||||
|
||||
R u2s(unsigned u) const { return (approx_set_traits<R>::one << (u & (approx_set_traits<R>::capacity - 1))); }
|
||||
|
||||
R e2s(T const & e) const { return u2s(e2u(e)); }
|
||||
|
||||
static approx_set_tpl r2s(R const & s) { approx_set_tpl r; r.m_set = s; return r; }
|
||||
|
||||
public:
|
||||
approx_set_tpl():
|
||||
m_set(approx_set_traits<R>::zero) {
|
||||
}
|
||||
|
||||
explicit approx_set_tpl(T const & e):
|
||||
m_set(e2s(e)) {
|
||||
}
|
||||
|
||||
approx_set_tpl(unsigned sz, T const * es):
|
||||
m_set(approx_set_traits<R>::zero) {
|
||||
for (unsigned i = 0; i < sz; i++)
|
||||
insert(es[i]);
|
||||
}
|
||||
|
||||
approx_set_tpl(approx_set_tpl const & s):
|
||||
m_set(s.m_set) {
|
||||
}
|
||||
|
||||
void insert(T const & e) {
|
||||
m_set |= e2s(e);
|
||||
}
|
||||
|
||||
bool may_contain(T const & e) const {
|
||||
return (m_set & e2s(e)) != approx_set_traits<R>::zero;
|
||||
}
|
||||
|
||||
bool must_not_contain(T const & e) const {
|
||||
return !may_contain(e);
|
||||
}
|
||||
|
||||
friend inline approx_set_tpl mk_union(approx_set_tpl const & s1, approx_set_tpl const & s2) {
|
||||
return r2s(s1.m_set | s2.m_set);
|
||||
}
|
||||
|
||||
friend inline approx_set_tpl mk_intersection(approx_set_tpl const & s1, approx_set_tpl const & s2) {
|
||||
return r2s(s1.m_set & s2.m_set);
|
||||
}
|
||||
|
||||
void operator|=(approx_set_tpl const & other) {
|
||||
m_set |= other.m_set;
|
||||
}
|
||||
|
||||
void operator&=(approx_set_tpl const & other) {
|
||||
m_set &= other.m_set;
|
||||
}
|
||||
|
||||
void operator-=(approx_set_tpl const & other) {
|
||||
m_set &= ~(other.m_set);
|
||||
}
|
||||
|
||||
bool empty() const {
|
||||
return m_set == approx_set_traits<R>::zero;
|
||||
}
|
||||
|
||||
friend inline bool empty(approx_set_tpl const & s) {
|
||||
return s.empty();
|
||||
}
|
||||
|
||||
bool must_not_subset(approx_set_tpl const & s2) const {
|
||||
return (m_set & ~(s2.m_set)) != approx_set_traits<R>::zero;
|
||||
}
|
||||
|
||||
friend inline bool must_not_subset(approx_set_tpl const & s1, approx_set_tpl const & s2) {
|
||||
return s1.must_not_subset(s2);
|
||||
}
|
||||
|
||||
bool must_not_subsume(approx_set_tpl const & s2) const {
|
||||
return must_not_subset(s2);
|
||||
}
|
||||
|
||||
friend inline bool must_not_subsume(approx_set_tpl const & s1, approx_set_tpl const & s2) {
|
||||
return s1.must_not_subset(s2);
|
||||
}
|
||||
|
||||
friend inline bool must_not_eq(approx_set_tpl const & s1, approx_set_tpl const & s2) { return s1.m_set != s2.m_set; }
|
||||
|
||||
friend inline bool may_eq(approx_set_tpl const & s1, approx_set_tpl const & s2) { return s1.m_set == s2.m_set; }
|
||||
|
||||
/**
|
||||
\brief Return if s1 and s2 are the same approximated set.
|
||||
*/
|
||||
bool equiv(approx_set_tpl const & s2) const { return m_set == s2.m_set; }
|
||||
friend inline bool equiv(approx_set_tpl const & s1, approx_set_tpl const & s2) { return s1.m_set == s2.m_set; }
|
||||
|
||||
/**
|
||||
\brief Return true if the approximation of s1 is a subset of the approximation of s2.
|
||||
*/
|
||||
friend inline bool approx_subset(approx_set_tpl const & s1, approx_set_tpl const & s2) {
|
||||
return s2.equiv(mk_union(s1, s2));
|
||||
}
|
||||
|
||||
void reset() {
|
||||
m_set = approx_set_traits<R>::zero;
|
||||
}
|
||||
|
||||
bool empty_intersection(approx_set_tpl const & other) const {
|
||||
return mk_intersection(*this, other).empty();
|
||||
}
|
||||
};
|
||||
|
||||
struct u2u { unsigned operator()(unsigned u) const { return u; } };
|
||||
|
||||
typedef approx_set_tpl<unsigned, u2u> u_approx_set;
|
||||
|
||||
#define APPROX_SET_CAPACITY (approx_set_traits<unsigned long long>::capacity)
|
||||
|
||||
class approx_set : public u_approx_set {
|
||||
public:
|
||||
approx_set():u_approx_set() {}
|
||||
approx_set(unsigned e):u_approx_set(e) {}
|
||||
|
||||
class iterator {
|
||||
unsigned long long m_set;
|
||||
unsigned m_val;
|
||||
void move_to_next() {
|
||||
// TODO: this code can be optimized in platforms with special
|
||||
// instructions to count leading (trailing) zeros in a word.
|
||||
while (m_set > 0) {
|
||||
if ((m_set & 1ull) != 0) {
|
||||
return;
|
||||
}
|
||||
m_val ++;
|
||||
m_set = m_set >> 1;
|
||||
}
|
||||
}
|
||||
public:
|
||||
iterator(unsigned long long s):
|
||||
m_set(s),
|
||||
m_val(0) {
|
||||
move_to_next();
|
||||
}
|
||||
|
||||
unsigned operator*() const {
|
||||
return m_val;
|
||||
}
|
||||
|
||||
iterator & operator++() {
|
||||
m_val++;
|
||||
m_set = m_set >> 1;
|
||||
move_to_next();
|
||||
return *this;
|
||||
}
|
||||
|
||||
iterator operator++(int) {
|
||||
iterator tmp = *this;
|
||||
++*this;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
bool operator==(iterator const & it) const {
|
||||
return m_set == it.m_set;
|
||||
}
|
||||
|
||||
bool operator!=(iterator const & it) const {
|
||||
return m_set != it.m_set;
|
||||
}
|
||||
};
|
||||
|
||||
iterator begin() const {
|
||||
return iterator(m_set);
|
||||
}
|
||||
|
||||
static iterator end() {
|
||||
return iterator(0);
|
||||
}
|
||||
|
||||
void display(std::ostream & out) const;
|
||||
|
||||
unsigned size() const;
|
||||
|
||||
// for backward compatibility
|
||||
friend inline bool operator==(approx_set const & s1, approx_set const & s2) { return may_eq(s1, s2); }
|
||||
};
|
||||
|
||||
inline std::ostream & operator<<(std::ostream & out, approx_set const & s) {
|
||||
s.display(out);
|
||||
return out;
|
||||
}
|
||||
|
||||
#endif /* _APPROX_SET_H_ */
|
||||
|
161
lib/arith_bounds_tactic.cpp
Normal file
161
lib/arith_bounds_tactic.cpp
Normal file
|
@ -0,0 +1,161 @@
|
|||
|
||||
|
||||
#include"arith_bounds_tactic.h"
|
||||
#include"assertion_set_util.h"
|
||||
#include"arith_decl_plugin.h"
|
||||
|
||||
struct arith_bounds_tactic : public tactic {
|
||||
|
||||
ast_manager& m;
|
||||
arith_util a;
|
||||
volatile bool m_cancel;
|
||||
|
||||
arith_bounds_tactic(ast_manager& m):
|
||||
m(m),
|
||||
a(m),
|
||||
m_cancel(false)
|
||||
{
|
||||
}
|
||||
|
||||
ast_manager& get_manager() { return m; }
|
||||
|
||||
void set_cancel(bool f) {
|
||||
m_cancel = f;
|
||||
}
|
||||
|
||||
virtual void cleanup() {
|
||||
m_cancel = false;
|
||||
}
|
||||
|
||||
virtual void operator()(/* in */ goal_ref const & in,
|
||||
/* out */ goal_ref_buffer & result,
|
||||
/* out */ model_converter_ref & mc,
|
||||
/* out */ proof_converter_ref & pc,
|
||||
/* out */ expr_dependency_ref & core) {
|
||||
bounds_arith_subsumption(in, result);
|
||||
}
|
||||
|
||||
virtual tactic* translate(ast_manager& m) {
|
||||
return alloc(arith_bounds_tactic, m);
|
||||
}
|
||||
|
||||
void checkpoint() {
|
||||
if (m_cancel) {
|
||||
throw tactic_exception(TACTIC_CANCELED_MSG);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct info { rational r; unsigned idx; bool is_strict;};
|
||||
|
||||
/**
|
||||
\brief Basic arithmetic subsumption simplification based on bounds.
|
||||
*/
|
||||
|
||||
void mk_proof(proof_ref& pr, goal_ref const& s, unsigned i, unsigned j) {
|
||||
if (s->proofs_enabled()) {
|
||||
proof* th_lemma = m.mk_th_lemma(a.get_family_id(), m.mk_implies(s->form(i), s->form(j)), 0, 0);
|
||||
pr = m.mk_modus_ponens(s->pr(i), th_lemma);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool is_le_or_lt(expr* e, expr*& e1, expr*& e2, bool& is_strict) {
|
||||
bool is_negated = m.is_not(e, e);
|
||||
if ((!is_negated && (a.is_le(e, e1, e2) || a.is_ge(e, e2, e1))) ||
|
||||
(is_negated && (a.is_lt(e, e2, e1) || a.is_gt(e, e1, e2)))) {
|
||||
is_strict = false;
|
||||
return true;
|
||||
}
|
||||
if ((!is_negated && (a.is_lt(e, e1, e2) || a.is_gt(e, e2, e1))) ||
|
||||
(is_negated && (a.is_le(e, e2, e1) || a.is_ge(e, e1, e2)))) {
|
||||
is_strict = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void bounds_arith_subsumption(goal_ref const& g, goal_ref_buffer& result) {
|
||||
info inf;
|
||||
rational r;
|
||||
goal_ref s(g); // initialize result.
|
||||
obj_map<expr, info> lower, upper;
|
||||
expr* e1, *e2;
|
||||
TRACE("arith_subsumption", s->display(tout); );
|
||||
for (unsigned i = 0; i < s->size(); ++i) {
|
||||
checkpoint();
|
||||
expr* lemma = s->form(i);
|
||||
bool is_strict = false;
|
||||
bool is_lower = false;
|
||||
if (!is_le_or_lt(lemma, e1, e2, is_strict)) {
|
||||
continue;
|
||||
}
|
||||
// e1 <= e2 or e1 < e2
|
||||
if (a.is_numeral(e2, r)) {
|
||||
is_lower = true;
|
||||
}
|
||||
else if (a.is_numeral(e1, r)) {
|
||||
is_lower = false;
|
||||
}
|
||||
else {
|
||||
continue;
|
||||
}
|
||||
proof_ref new_pr(m);
|
||||
|
||||
if (is_lower && upper.find(e1, inf)) {
|
||||
if (inf.r > r || (inf.r == r && is_strict && !inf.is_strict)) {
|
||||
mk_proof(new_pr, s, i, inf.idx);
|
||||
s->update(inf.idx, m.mk_true(), new_pr);
|
||||
inf.r = r;
|
||||
inf.is_strict = is_strict;
|
||||
inf.idx = i;
|
||||
upper.insert(e1, inf);
|
||||
}
|
||||
else {
|
||||
mk_proof(new_pr, s, inf.idx, i);
|
||||
s->update(i, m.mk_true(), new_pr);
|
||||
}
|
||||
}
|
||||
else if (is_lower) {
|
||||
inf.r = r;
|
||||
inf.is_strict = is_strict;
|
||||
inf.idx = i;
|
||||
upper.insert(e1, inf);
|
||||
}
|
||||
else if (!is_lower && lower.find(e2, inf)) {
|
||||
if (inf.r < r || (inf.r == r && is_strict && !inf.is_strict)) {
|
||||
mk_proof(new_pr, s, i, inf.idx);
|
||||
s->update(inf.idx, m.mk_true(), new_pr);
|
||||
inf.r = r;
|
||||
inf.is_strict = is_strict;
|
||||
inf.idx = i;
|
||||
lower.insert(e2, inf);
|
||||
}
|
||||
else {
|
||||
mk_proof(new_pr, s, inf.idx, i);
|
||||
s->update(i, m.mk_true());
|
||||
}
|
||||
}
|
||||
else if (!is_lower) {
|
||||
inf.r = r;
|
||||
inf.is_strict = is_strict;
|
||||
inf.idx = i;
|
||||
lower.insert(e2, inf);
|
||||
}
|
||||
}
|
||||
s->elim_true();
|
||||
result.push_back(s.get());
|
||||
TRACE("arith_subsumption", s->display(tout); );
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
tactic * mk_arith_bounds_tactic(ast_manager & m, params_ref const & p) {
|
||||
return alloc(arith_bounds_tactic, m);
|
||||
}
|
||||
|
||||
|
37
lib/arith_bounds_tactic.h
Normal file
37
lib/arith_bounds_tactic.h
Normal file
|
@ -0,0 +1,37 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
arith_bounds_tactic.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Fast/rudimentary arithmetic subsumption tactic.
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2012-9-6
|
||||
|
||||
Notes:
|
||||
|
||||
Background: The Farkas learner in PDR generates tons
|
||||
of inequalities that contain redundancies.
|
||||
It therefore needs a fast way to reduce these redundancies before
|
||||
passing the results to routines that are more expensive.
|
||||
The arith subsumption_strategy encapsulates a rudimentary
|
||||
routine for simplifying inequalities. Additional simplification
|
||||
routines can be added here or composed with this strategy.
|
||||
|
||||
Note: The bound_manager subsumes some of the collection methods used
|
||||
for assembling bounds, but it does not have a way to check for
|
||||
subsumption of atoms.
|
||||
|
||||
--*/
|
||||
#ifndef _ARITH_BOUNDS_TACTIC_H_
|
||||
#define _ARITH_BOUNDS_TACTIC_H_
|
||||
#include "tactic.h"
|
||||
|
||||
tactic * mk_arith_bounds_tactic(ast_manager & m, params_ref const & p = params_ref());
|
||||
|
||||
#endif
|
558
lib/arith_decl_plugin.cpp
Normal file
558
lib/arith_decl_plugin.cpp
Normal file
|
@ -0,0 +1,558 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
arith_decl_plugin.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
<abstract>
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-01-09
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include"arith_decl_plugin.h"
|
||||
#include"warning.h"
|
||||
#include"algebraic_numbers.h"
|
||||
#include"id_gen.h"
|
||||
#include"ast_smt2_pp.h"
|
||||
|
||||
struct arith_decl_plugin::algebraic_numbers_wrapper {
|
||||
unsynch_mpq_manager m_qmanager;
|
||||
algebraic_numbers::manager m_amanager;
|
||||
id_gen m_id_gen;
|
||||
scoped_anum_vector m_nums;
|
||||
|
||||
algebraic_numbers_wrapper():
|
||||
m_amanager(m_qmanager),
|
||||
m_nums(m_amanager) {
|
||||
}
|
||||
|
||||
~algebraic_numbers_wrapper() {
|
||||
}
|
||||
|
||||
unsigned mk_id(algebraic_numbers::anum const & val) {
|
||||
SASSERT(!m_amanager.is_rational(val));
|
||||
// TODO: avoid linear scan. Use hashtable based on the floor of val
|
||||
unsigned sz = m_nums.size();
|
||||
for (unsigned i = 0; i < sz; i++) {
|
||||
algebraic_numbers::anum const & other = m_nums.get(i);
|
||||
if (m_amanager.eq(val, other))
|
||||
return i;
|
||||
}
|
||||
unsigned new_id = m_id_gen.mk();
|
||||
m_nums.reserve(new_id+1);
|
||||
m_amanager.set(m_nums[new_id], val);
|
||||
TRACE("algebraic2expr", tout << "mk_id -> " << new_id << "\n"; m_amanager.display(tout, val); tout << "\n";);
|
||||
return new_id;
|
||||
}
|
||||
|
||||
void recycle_id(unsigned idx) {
|
||||
SASSERT(idx < m_nums.size());
|
||||
SASSERT(!m_amanager.is_zero(m_nums[idx]));
|
||||
TRACE("algebraic2expr", tout << "recycling: " << idx << "\n";);
|
||||
m_id_gen.recycle(idx);
|
||||
m_amanager.del(m_nums[idx]);
|
||||
}
|
||||
|
||||
algebraic_numbers::anum const & idx2anum(unsigned idx) {
|
||||
return m_nums[idx];
|
||||
}
|
||||
|
||||
algebraic_numbers::anum const & to_anum(func_decl * f) {
|
||||
SASSERT(f->get_decl_kind() == OP_IRRATIONAL_ALGEBRAIC_NUM);
|
||||
return idx2anum(f->get_parameter(0).get_ext_id());
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
arith_decl_plugin::algebraic_numbers_wrapper & arith_decl_plugin::aw() {
|
||||
if (m_aw == 0)
|
||||
m_aw = alloc(algebraic_numbers_wrapper);
|
||||
return *m_aw;
|
||||
}
|
||||
|
||||
algebraic_numbers::manager & arith_decl_plugin::am() {
|
||||
return aw().m_amanager;
|
||||
}
|
||||
|
||||
app * arith_decl_plugin::mk_numeral(algebraic_numbers::anum const & val, bool is_int) {
|
||||
if (am().is_rational(val)) {
|
||||
rational rval;
|
||||
am().to_rational(val, rval);
|
||||
return mk_numeral(rval, is_int);
|
||||
}
|
||||
else {
|
||||
if (is_int)
|
||||
m_manager->raise_exception("invalid irrational value passed as an integer");
|
||||
unsigned idx = aw().mk_id(val);
|
||||
parameter p(idx, true);
|
||||
SASSERT(p.is_external());
|
||||
func_decl * decl = m_manager->mk_const_decl(m_rootv_sym, m_real_decl, func_decl_info(m_family_id, OP_IRRATIONAL_ALGEBRAIC_NUM, 1, &p));
|
||||
return m_manager->mk_const(decl);
|
||||
}
|
||||
}
|
||||
|
||||
app * arith_decl_plugin::mk_numeral(sexpr const * p, unsigned i) {
|
||||
scoped_anum r(am());
|
||||
am().mk_root(p, i, r);
|
||||
return mk_numeral(r, false);
|
||||
}
|
||||
|
||||
void arith_decl_plugin::del(parameter const & p) {
|
||||
SASSERT(p.is_external());
|
||||
if (m_aw != 0) {
|
||||
aw().recycle_id(p.get_ext_id());
|
||||
}
|
||||
}
|
||||
|
||||
parameter arith_decl_plugin::translate(parameter const & p, decl_plugin & target) {
|
||||
SASSERT(p.is_external());
|
||||
arith_decl_plugin & _target = static_cast<arith_decl_plugin&>(target);
|
||||
return parameter(_target.aw().mk_id(aw().idx2anum(p.get_ext_id())), true);
|
||||
}
|
||||
|
||||
void arith_decl_plugin::set_cancel(bool f) {
|
||||
if (m_aw)
|
||||
m_aw->m_amanager.set_cancel(f);
|
||||
}
|
||||
|
||||
void arith_decl_plugin::set_manager(ast_manager * m, family_id id) {
|
||||
decl_plugin::set_manager(m, id);
|
||||
|
||||
m_real_decl = m->mk_sort(symbol("Real"), sort_info(id, REAL_SORT));
|
||||
m->inc_ref(m_real_decl);
|
||||
sort * r = m_real_decl;
|
||||
|
||||
m_int_decl = m->mk_sort(symbol("Int"), sort_info(id, INT_SORT));
|
||||
m->inc_ref(m_int_decl);
|
||||
sort * i = m_int_decl;
|
||||
|
||||
sort * b = m->mk_bool_sort();
|
||||
|
||||
#define MK_PRED(FIELD, NAME, KIND, SORT) { \
|
||||
func_decl_info info(id, KIND); \
|
||||
info.set_chainable(true); \
|
||||
FIELD = m->mk_func_decl(symbol(NAME), SORT, SORT, b, info); \
|
||||
m->inc_ref(FIELD); \
|
||||
}
|
||||
|
||||
MK_PRED(m_r_le_decl, "<=", OP_LE, r);
|
||||
MK_PRED(m_r_ge_decl, ">=", OP_GE, r);
|
||||
MK_PRED(m_r_lt_decl, "<", OP_LT, r);
|
||||
MK_PRED(m_r_gt_decl, ">", OP_GT, r);
|
||||
|
||||
MK_PRED(m_i_le_decl, "<=", OP_LE, i);
|
||||
MK_PRED(m_i_ge_decl, ">=", OP_GE, i);
|
||||
MK_PRED(m_i_lt_decl, "<", OP_LT, i);
|
||||
MK_PRED(m_i_gt_decl, ">", OP_GT, i);
|
||||
|
||||
#define MK_AC_OP(FIELD, NAME, KIND, SORT) { \
|
||||
func_decl_info info(id, KIND); \
|
||||
info.set_associative(); \
|
||||
info.set_flat_associative(); \
|
||||
info.set_commutative(); \
|
||||
FIELD = m->mk_func_decl(symbol(NAME), SORT, SORT, SORT, info); \
|
||||
m->inc_ref(FIELD); \
|
||||
}
|
||||
|
||||
#define MK_OP(FIELD, NAME, KIND, SORT) \
|
||||
FIELD = m->mk_func_decl(symbol(NAME), SORT, SORT, SORT, func_decl_info(id, KIND)); \
|
||||
m->inc_ref(FIELD)
|
||||
|
||||
#define MK_UNARY(FIELD, NAME, KIND, SORT) \
|
||||
FIELD = m->mk_func_decl(symbol(NAME), SORT, SORT, func_decl_info(id, KIND)); \
|
||||
m->inc_ref(FIELD)
|
||||
|
||||
MK_AC_OP(m_r_add_decl, "+", OP_ADD, r);
|
||||
MK_OP(m_r_sub_decl, "-", OP_SUB, r);
|
||||
MK_AC_OP(m_r_mul_decl, "*", OP_MUL, r);
|
||||
MK_OP(m_r_div_decl, "/", OP_DIV, r);
|
||||
MK_UNARY(m_r_uminus_decl, "-", OP_UMINUS, r);
|
||||
|
||||
MK_AC_OP(m_i_add_decl, "+", OP_ADD, i);
|
||||
MK_OP(m_i_sub_decl, "-", OP_SUB, i);
|
||||
MK_AC_OP(m_i_mul_decl, "*", OP_MUL, i);
|
||||
MK_OP(m_i_div_decl, "div", OP_IDIV, i);
|
||||
MK_OP(m_i_rem_decl, "rem", OP_REM, i);
|
||||
MK_OP(m_i_mod_decl, "mod", OP_MOD, i);
|
||||
MK_UNARY(m_i_uminus_decl, "-", OP_UMINUS, i);
|
||||
|
||||
m_to_real_decl = m->mk_func_decl(symbol("to_real"), i, r, func_decl_info(id, OP_TO_REAL));
|
||||
m->inc_ref(m_to_real_decl);
|
||||
m_to_int_decl = m->mk_func_decl(symbol("to_int"), r, i, func_decl_info(id, OP_TO_INT));
|
||||
m->inc_ref(m_to_int_decl);
|
||||
m_is_int_decl = m->mk_func_decl(symbol("is_int"), r, m->mk_bool_sort(), func_decl_info(id, OP_IS_INT));
|
||||
m->inc_ref(m_is_int_decl);
|
||||
|
||||
MK_OP(m_r_power_decl, "^", OP_POWER, r);
|
||||
MK_OP(m_i_power_decl, "^", OP_POWER, i);
|
||||
|
||||
MK_UNARY(m_sin_decl, "sin", OP_SIN, r);
|
||||
MK_UNARY(m_cos_decl, "cos", OP_COS, r);
|
||||
MK_UNARY(m_tan_decl, "tan", OP_TAN, r);
|
||||
MK_UNARY(m_asin_decl, "asin", OP_ASIN, r);
|
||||
MK_UNARY(m_acos_decl, "acos", OP_ACOS, r);
|
||||
MK_UNARY(m_atan_decl, "atan", OP_ATAN, r);
|
||||
MK_UNARY(m_sinh_decl, "sinh", OP_SINH, r);
|
||||
MK_UNARY(m_cosh_decl, "cosh", OP_COSH, r);
|
||||
MK_UNARY(m_tanh_decl, "tanh", OP_TANH, r);
|
||||
MK_UNARY(m_asinh_decl, "asinh", OP_ASINH, r);
|
||||
MK_UNARY(m_acosh_decl, "acosh", OP_ACOSH, r);
|
||||
MK_UNARY(m_atanh_decl, "atanh", OP_ATANH, r);
|
||||
|
||||
func_decl * pi_decl = m->mk_const_decl(symbol("pi"), r, func_decl_info(id, OP_PI));
|
||||
m_pi = m->mk_const(pi_decl);
|
||||
m->inc_ref(m_pi);
|
||||
|
||||
func_decl * e_decl = m->mk_const_decl(symbol("euler"), r, func_decl_info(id, OP_E));
|
||||
m_e = m->mk_const(e_decl);
|
||||
m->inc_ref(m_e);
|
||||
}
|
||||
|
||||
arith_decl_plugin::arith_decl_plugin():
|
||||
m_aw(0),
|
||||
m_intv_sym("Int"),
|
||||
m_realv_sym("Real"),
|
||||
m_rootv_sym("RootObject"),
|
||||
m_real_decl(0),
|
||||
m_int_decl(0),
|
||||
m_r_le_decl(0),
|
||||
m_r_ge_decl(0),
|
||||
m_r_lt_decl(0),
|
||||
m_r_gt_decl(0),
|
||||
m_r_add_decl(0),
|
||||
m_r_sub_decl(0),
|
||||
m_r_uminus_decl(0),
|
||||
m_r_mul_decl(0),
|
||||
m_r_div_decl(0),
|
||||
m_i_le_decl(0),
|
||||
m_i_ge_decl(0),
|
||||
m_i_lt_decl(0),
|
||||
m_i_gt_decl(0),
|
||||
m_i_add_decl(0),
|
||||
m_i_sub_decl(0),
|
||||
m_i_uminus_decl(0),
|
||||
m_i_mul_decl(0),
|
||||
m_i_div_decl(0),
|
||||
m_i_mod_decl(0),
|
||||
m_i_rem_decl(0),
|
||||
m_to_real_decl(0),
|
||||
m_to_int_decl(0),
|
||||
m_is_int_decl(0),
|
||||
m_r_power_decl(0),
|
||||
m_i_power_decl(0),
|
||||
m_sin_decl(0),
|
||||
m_cos_decl(0),
|
||||
m_tan_decl(0),
|
||||
m_asin_decl(0),
|
||||
m_acos_decl(0),
|
||||
m_atan_decl(0),
|
||||
m_sinh_decl(0),
|
||||
m_cosh_decl(0),
|
||||
m_tanh_decl(0),
|
||||
m_asinh_decl(0),
|
||||
m_acosh_decl(0),
|
||||
m_atanh_decl(0),
|
||||
m_pi(0),
|
||||
m_e(0) {
|
||||
}
|
||||
|
||||
arith_decl_plugin::~arith_decl_plugin() {
|
||||
dealloc(m_aw);
|
||||
}
|
||||
|
||||
void arith_decl_plugin::finalize() {
|
||||
#define DEC_REF(decl) if (decl) { m_manager->dec_ref(decl); } ((void) 0)
|
||||
DEC_REF(m_real_decl);
|
||||
DEC_REF(m_int_decl);
|
||||
DEC_REF(m_r_le_decl);
|
||||
DEC_REF(m_r_ge_decl);
|
||||
DEC_REF(m_r_lt_decl);
|
||||
DEC_REF(m_r_gt_decl);
|
||||
DEC_REF(m_r_add_decl);
|
||||
DEC_REF(m_r_sub_decl);
|
||||
DEC_REF(m_r_uminus_decl);
|
||||
DEC_REF(m_r_mul_decl);
|
||||
DEC_REF(m_r_div_decl);
|
||||
DEC_REF(m_i_le_decl);
|
||||
DEC_REF(m_i_ge_decl);
|
||||
DEC_REF(m_i_lt_decl);
|
||||
DEC_REF(m_i_gt_decl);
|
||||
DEC_REF(m_i_add_decl);
|
||||
DEC_REF(m_i_sub_decl);
|
||||
DEC_REF(m_i_uminus_decl);
|
||||
DEC_REF(m_i_mul_decl);
|
||||
DEC_REF(m_i_div_decl);
|
||||
DEC_REF(m_i_mod_decl);
|
||||
DEC_REF(m_i_rem_decl);
|
||||
DEC_REF(m_to_real_decl);
|
||||
DEC_REF(m_to_int_decl);
|
||||
DEC_REF(m_is_int_decl);
|
||||
DEC_REF(m_i_power_decl);
|
||||
DEC_REF(m_r_power_decl);
|
||||
DEC_REF(m_sin_decl);
|
||||
DEC_REF(m_cos_decl);
|
||||
DEC_REF(m_tan_decl);
|
||||
DEC_REF(m_asin_decl);
|
||||
DEC_REF(m_acos_decl);
|
||||
DEC_REF(m_atan_decl);
|
||||
DEC_REF(m_sinh_decl);
|
||||
DEC_REF(m_cosh_decl);
|
||||
DEC_REF(m_tanh_decl);
|
||||
DEC_REF(m_asinh_decl);
|
||||
DEC_REF(m_acosh_decl);
|
||||
DEC_REF(m_atanh_decl);
|
||||
DEC_REF(m_pi);
|
||||
DEC_REF(m_e);
|
||||
m_manager->dec_array_ref(m_small_ints.size(), m_small_ints.c_ptr());
|
||||
m_manager->dec_array_ref(m_small_reals.size(), m_small_reals.c_ptr());
|
||||
}
|
||||
|
||||
sort * arith_decl_plugin::mk_sort(decl_kind k, unsigned num_parameters, parameter const * parameters) {
|
||||
switch (k) {
|
||||
case REAL_SORT: return m_real_decl;
|
||||
case INT_SORT: return m_int_decl;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
inline func_decl * arith_decl_plugin::mk_func_decl(decl_kind k, bool is_real) {
|
||||
switch (k) {
|
||||
case OP_LE: return is_real ? m_r_le_decl : m_i_le_decl;
|
||||
case OP_GE: return is_real ? m_r_ge_decl : m_i_ge_decl;
|
||||
case OP_LT: return is_real ? m_r_lt_decl : m_i_lt_decl;
|
||||
case OP_GT: return is_real ? m_r_gt_decl : m_i_gt_decl;
|
||||
case OP_ADD: return is_real ? m_r_add_decl : m_i_add_decl;
|
||||
case OP_SUB: return is_real ? m_r_sub_decl : m_i_sub_decl;
|
||||
case OP_UMINUS: return is_real ? m_r_uminus_decl : m_i_uminus_decl;
|
||||
case OP_MUL: return is_real ? m_r_mul_decl : m_i_mul_decl;
|
||||
case OP_DIV: SASSERT(is_real); return m_r_div_decl;
|
||||
case OP_IDIV: SASSERT(!is_real); return m_i_div_decl;
|
||||
case OP_REM: return m_i_rem_decl;
|
||||
case OP_MOD: return m_i_mod_decl;
|
||||
case OP_TO_REAL: return m_to_real_decl;
|
||||
case OP_TO_INT: return m_to_int_decl;
|
||||
case OP_IS_INT: return m_is_int_decl;
|
||||
case OP_POWER: return is_real ? m_r_power_decl : m_i_power_decl;
|
||||
case OP_SIN: return m_sin_decl;
|
||||
case OP_COS: return m_cos_decl;
|
||||
case OP_TAN: return m_tan_decl;
|
||||
case OP_ASIN: return m_asin_decl;
|
||||
case OP_ACOS: return m_acos_decl;
|
||||
case OP_ATAN: return m_atan_decl;
|
||||
case OP_SINH: return m_sinh_decl;
|
||||
case OP_COSH: return m_cosh_decl;
|
||||
case OP_TANH: return m_tanh_decl;
|
||||
case OP_ASINH: return m_asinh_decl;
|
||||
case OP_ACOSH: return m_acosh_decl;
|
||||
case OP_ATANH: return m_atanh_decl;
|
||||
case OP_PI: return m_pi->get_decl();
|
||||
case OP_E: return m_e->get_decl();
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
inline decl_kind arith_decl_plugin::fix_kind(decl_kind k, unsigned arity) {
|
||||
if (k == OP_SUB && arity == 1) {
|
||||
return OP_UMINUS;
|
||||
}
|
||||
return k;
|
||||
}
|
||||
|
||||
#define MAX_SMALL_NUM_TO_CACHE 16
|
||||
|
||||
app * arith_decl_plugin::mk_numeral(rational const & val, bool is_int) {
|
||||
if (is_int && !val.is_int()) {
|
||||
m_manager->raise_exception("invalid rational value passed as an integer");
|
||||
}
|
||||
if (val.is_unsigned()) {
|
||||
unsigned u_val = val.get_unsigned();
|
||||
if (u_val < MAX_SMALL_NUM_TO_CACHE) {
|
||||
if (is_int) {
|
||||
app * r = m_small_ints.get(u_val, 0);
|
||||
if (r == 0) {
|
||||
parameter p[2] = { parameter(val), parameter(1) };
|
||||
r = m_manager->mk_const(m_manager->mk_const_decl(m_intv_sym, m_int_decl, func_decl_info(m_family_id, OP_NUM, 2, p)));
|
||||
m_manager->inc_ref(r);
|
||||
m_small_ints.setx(u_val, r, 0);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
else {
|
||||
app * r = m_small_reals.get(u_val, 0);
|
||||
if (r == 0) {
|
||||
parameter p[2] = { parameter(val), parameter(0) };
|
||||
r = m_manager->mk_const(m_manager->mk_const_decl(m_realv_sym, m_real_decl, func_decl_info(m_family_id, OP_NUM, 2, p)));
|
||||
m_manager->inc_ref(r);
|
||||
m_small_reals.setx(u_val, r, 0);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
}
|
||||
}
|
||||
parameter p[2] = { parameter(val), parameter(static_cast<int>(is_int)) };
|
||||
func_decl * decl;
|
||||
if (is_int)
|
||||
decl = m_manager->mk_const_decl(m_intv_sym, m_int_decl, func_decl_info(m_family_id, OP_NUM, 2, p));
|
||||
else
|
||||
decl = m_manager->mk_const_decl(m_realv_sym, m_real_decl, func_decl_info(m_family_id, OP_NUM, 2, p));
|
||||
return m_manager->mk_const(decl);
|
||||
}
|
||||
|
||||
func_decl * arith_decl_plugin::mk_num_decl(unsigned num_parameters, parameter const * parameters, unsigned arity) {
|
||||
if (!(num_parameters == 2 && arity == 0 && parameters[0].is_rational() && parameters[1].is_int())) {
|
||||
m_manager->raise_exception("invalid numeral declaration");
|
||||
return 0;
|
||||
}
|
||||
if (parameters[1].get_int() != 0)
|
||||
return m_manager->mk_const_decl(m_intv_sym, m_int_decl, func_decl_info(m_family_id, OP_NUM, num_parameters, parameters));
|
||||
else
|
||||
return m_manager->mk_const_decl(m_realv_sym, m_real_decl, func_decl_info(m_family_id, OP_NUM, num_parameters, parameters));
|
||||
}
|
||||
|
||||
func_decl * arith_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters, parameter const * parameters,
|
||||
unsigned arity, sort * const * domain, sort * range) {
|
||||
if (k == OP_NUM)
|
||||
return mk_num_decl(num_parameters, parameters, arity);
|
||||
if (arity == 0 && k != OP_PI && k != OP_E) {
|
||||
m_manager->raise_exception("no arguments supplied to arithmetical operator");
|
||||
return 0;
|
||||
}
|
||||
bool is_real = arity > 0 && domain[0] == m_real_decl;
|
||||
return mk_func_decl(fix_kind(k, arity), is_real);
|
||||
}
|
||||
|
||||
func_decl * arith_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters, parameter const * parameters,
|
||||
unsigned num_args, expr * const * args, sort * range) {
|
||||
if (k == OP_NUM)
|
||||
return mk_num_decl(num_parameters, parameters, num_args);
|
||||
if (num_args == 0 && k != OP_PI && k != OP_E) {
|
||||
m_manager->raise_exception("no arguments supplied to arithmetical operator");
|
||||
return 0;
|
||||
}
|
||||
bool is_real = num_args > 0 && m_manager->get_sort(args[0]) == m_real_decl;
|
||||
return mk_func_decl(fix_kind(k, num_args), is_real);
|
||||
}
|
||||
|
||||
void arith_decl_plugin::get_sort_names(svector<builtin_name>& sort_names, symbol const & logic) {
|
||||
// TODO: only define Int and Real in the right logics
|
||||
sort_names.push_back(builtin_name("Int", INT_SORT));
|
||||
sort_names.push_back(builtin_name("Real", REAL_SORT));
|
||||
}
|
||||
|
||||
void arith_decl_plugin::get_op_names(svector<builtin_name>& op_names, symbol const & logic) {
|
||||
op_names.push_back(builtin_name("<=",OP_LE));
|
||||
op_names.push_back(builtin_name(">=",OP_GE));
|
||||
op_names.push_back(builtin_name("<",OP_LT));
|
||||
op_names.push_back(builtin_name(">",OP_GT));
|
||||
op_names.push_back(builtin_name("+",OP_ADD));
|
||||
op_names.push_back(builtin_name("-",OP_SUB));
|
||||
op_names.push_back(builtin_name("~",OP_UMINUS));
|
||||
op_names.push_back(builtin_name("*",OP_MUL));
|
||||
op_names.push_back(builtin_name("/",OP_DIV));
|
||||
op_names.push_back(builtin_name("div",OP_IDIV));
|
||||
op_names.push_back(builtin_name("rem",OP_REM));
|
||||
op_names.push_back(builtin_name("mod",OP_MOD));
|
||||
op_names.push_back(builtin_name("to_real",OP_TO_REAL));
|
||||
op_names.push_back(builtin_name("to_int",OP_TO_INT));
|
||||
op_names.push_back(builtin_name("is_int",OP_IS_INT));
|
||||
if (logic == symbol::null) {
|
||||
op_names.push_back(builtin_name("^", OP_POWER));
|
||||
op_names.push_back(builtin_name("sin", OP_SIN));
|
||||
op_names.push_back(builtin_name("cos", OP_COS));
|
||||
op_names.push_back(builtin_name("tan", OP_TAN));
|
||||
op_names.push_back(builtin_name("asin", OP_ASIN));
|
||||
op_names.push_back(builtin_name("acos", OP_ACOS));
|
||||
op_names.push_back(builtin_name("atan", OP_ATAN));
|
||||
op_names.push_back(builtin_name("sinh", OP_SINH));
|
||||
op_names.push_back(builtin_name("cosh", OP_COSH));
|
||||
op_names.push_back(builtin_name("tanh", OP_TANH));
|
||||
op_names.push_back(builtin_name("asinh", OP_ASINH));
|
||||
op_names.push_back(builtin_name("acosh", OP_ACOSH));
|
||||
op_names.push_back(builtin_name("atanh", OP_ATANH));
|
||||
op_names.push_back(builtin_name("pi", OP_PI));
|
||||
op_names.push_back(builtin_name("euler", OP_E));
|
||||
}
|
||||
}
|
||||
|
||||
bool arith_decl_plugin::is_value(app* e) const {
|
||||
return is_app_of(e, m_family_id, OP_NUM);
|
||||
}
|
||||
|
||||
bool arith_decl_plugin::are_distinct(app* a, app* b) const {
|
||||
TRACE("are_distinct_bug", tout << mk_ismt2_pp(a, *m_manager) << "\n" << mk_ismt2_pp(b, *m_manager) << "\n";);
|
||||
if (decl_plugin::are_distinct(a,b)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
#define is_non_zero(e) is_app_of(e,m_family_id, OP_NUM) && !to_app(e)->get_decl()->get_parameter(0).get_rational().is_zero()
|
||||
|
||||
if (is_app_of(a, m_family_id, OP_ADD) &&
|
||||
a->get_num_args() == 2 &&
|
||||
to_app(a)->get_arg(0) == b &&
|
||||
is_non_zero(to_app(a)->get_arg(1))) {
|
||||
return true;
|
||||
}
|
||||
if (is_app_of(a, m_family_id, OP_ADD) &&
|
||||
a->get_num_args() == 2 &&
|
||||
to_app(a)->get_arg(1) == b &&
|
||||
is_non_zero(to_app(a)->get_arg(0))) {
|
||||
return true;
|
||||
}
|
||||
if (is_app_of(b, m_family_id, OP_ADD) &&
|
||||
b->get_num_args() == 2 &&
|
||||
to_app(b)->get_arg(1) == a &&
|
||||
is_non_zero(to_app(b)->get_arg(0))) {
|
||||
return true;
|
||||
}
|
||||
if (is_app_of(b, m_family_id, OP_ADD) &&
|
||||
b->get_num_args() == 2 &&
|
||||
to_app(b)->get_arg(0) == a &&
|
||||
is_non_zero(to_app(b)->get_arg(1))) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
expr * arith_decl_plugin::get_some_value(sort * s) {
|
||||
SASSERT(s == m_int_decl || s == m_real_decl);
|
||||
return mk_numeral(rational(0), s == m_int_decl);
|
||||
}
|
||||
|
||||
arith_util::arith_util(ast_manager & m):
|
||||
m_manager(m),
|
||||
m_afid(m.get_family_id("arith")),
|
||||
m_plugin(0) {
|
||||
}
|
||||
|
||||
void arith_util::init_plugin() {
|
||||
SASSERT(m_plugin == 0);
|
||||
m_plugin = static_cast<arith_decl_plugin*>(m_manager.get_plugin(m_afid));
|
||||
}
|
||||
|
||||
bool arith_util::is_numeral(expr const * n, rational & val, bool & is_int) const {
|
||||
if (!is_app_of(n, m_afid, OP_NUM))
|
||||
return false;
|
||||
func_decl * decl = to_app(n)->get_decl();
|
||||
val = decl->get_parameter(0).get_rational();
|
||||
is_int = decl->get_parameter(1).get_int() != 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool arith_util::is_irrational_algebraic_numeral(expr const * n, algebraic_numbers::anum & val) {
|
||||
if (!is_app_of(n, m_afid, OP_IRRATIONAL_ALGEBRAIC_NUM))
|
||||
return false;
|
||||
am().set(val, to_irrational_algebraic_numeral(n));
|
||||
return true;
|
||||
}
|
||||
|
||||
algebraic_numbers::anum const & arith_util::to_irrational_algebraic_numeral(expr const * n) {
|
||||
SASSERT(is_irrational_algebraic_numeral(n));
|
||||
return plugin().aw().to_anum(to_app(n)->get_decl());
|
||||
}
|
348
lib/arith_decl_plugin.h
Normal file
348
lib/arith_decl_plugin.h
Normal file
|
@ -0,0 +1,348 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
arith_decl_plugin.h
|
||||
|
||||
Abstract:
|
||||
|
||||
<abstract>
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-01-09
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _ARITH_DECL_PLUGIN_H_
|
||||
#define _ARITH_DECL_PLUGIN_H_
|
||||
|
||||
#include"ast.h"
|
||||
class sexpr;
|
||||
|
||||
namespace algebraic_numbers {
|
||||
class anum;
|
||||
class manager;
|
||||
};
|
||||
|
||||
enum arith_sort_kind {
|
||||
REAL_SORT,
|
||||
INT_SORT
|
||||
};
|
||||
|
||||
enum arith_op_kind {
|
||||
OP_NUM, // rational & integers
|
||||
OP_IRRATIONAL_ALGEBRAIC_NUM, // irrationals that are roots of polynomials with integer coefficients
|
||||
OP_LE,
|
||||
OP_GE,
|
||||
OP_LT,
|
||||
OP_GT,
|
||||
OP_ADD,
|
||||
OP_SUB,
|
||||
OP_UMINUS,
|
||||
OP_MUL,
|
||||
OP_DIV,
|
||||
OP_IDIV,
|
||||
OP_REM,
|
||||
OP_MOD,
|
||||
OP_TO_REAL,
|
||||
OP_TO_INT,
|
||||
OP_IS_INT,
|
||||
OP_POWER,
|
||||
// hyperbolic and trigonometric functions
|
||||
OP_SIN,
|
||||
OP_COS,
|
||||
OP_TAN,
|
||||
OP_ASIN,
|
||||
OP_ACOS,
|
||||
OP_ATAN,
|
||||
OP_SINH,
|
||||
OP_COSH,
|
||||
OP_TANH,
|
||||
OP_ASINH,
|
||||
OP_ACOSH,
|
||||
OP_ATANH,
|
||||
// constants
|
||||
OP_PI,
|
||||
OP_E,
|
||||
LAST_ARITH_OP
|
||||
};
|
||||
|
||||
class arith_util;
|
||||
|
||||
class arith_decl_plugin : public decl_plugin {
|
||||
protected:
|
||||
struct algebraic_numbers_wrapper;
|
||||
algebraic_numbers_wrapper * m_aw;
|
||||
symbol m_intv_sym;
|
||||
symbol m_realv_sym;
|
||||
symbol m_rootv_sym;
|
||||
sort * m_real_decl;
|
||||
sort * m_int_decl;
|
||||
func_decl * m_r_le_decl;
|
||||
func_decl * m_r_ge_decl;
|
||||
func_decl * m_r_lt_decl;
|
||||
func_decl * m_r_gt_decl;
|
||||
|
||||
func_decl * m_r_add_decl;
|
||||
func_decl * m_r_sub_decl;
|
||||
func_decl * m_r_uminus_decl;
|
||||
func_decl * m_r_mul_decl;
|
||||
func_decl * m_r_div_decl;
|
||||
|
||||
func_decl * m_i_le_decl;
|
||||
func_decl * m_i_ge_decl;
|
||||
func_decl * m_i_lt_decl;
|
||||
func_decl * m_i_gt_decl;
|
||||
|
||||
func_decl * m_i_add_decl;
|
||||
func_decl * m_i_sub_decl;
|
||||
func_decl * m_i_uminus_decl;
|
||||
func_decl * m_i_mul_decl;
|
||||
func_decl * m_i_div_decl;
|
||||
func_decl * m_i_mod_decl;
|
||||
func_decl * m_i_rem_decl;
|
||||
|
||||
func_decl * m_to_real_decl;
|
||||
func_decl * m_to_int_decl;
|
||||
func_decl * m_is_int_decl;
|
||||
func_decl * m_r_power_decl;
|
||||
func_decl * m_i_power_decl;
|
||||
|
||||
func_decl * m_sin_decl;
|
||||
func_decl * m_cos_decl;
|
||||
func_decl * m_tan_decl;
|
||||
func_decl * m_asin_decl;
|
||||
func_decl * m_acos_decl;
|
||||
func_decl * m_atan_decl;
|
||||
func_decl * m_sinh_decl;
|
||||
func_decl * m_cosh_decl;
|
||||
func_decl * m_tanh_decl;
|
||||
func_decl * m_asinh_decl;
|
||||
func_decl * m_acosh_decl;
|
||||
func_decl * m_atanh_decl;
|
||||
|
||||
app * m_pi;
|
||||
app * m_e;
|
||||
|
||||
ptr_vector<app> m_small_ints;
|
||||
ptr_vector<app> m_small_reals;
|
||||
|
||||
func_decl * mk_func_decl(decl_kind k, bool is_real);
|
||||
virtual void set_manager(ast_manager * m, family_id id);
|
||||
decl_kind fix_kind(decl_kind k, unsigned arity);
|
||||
func_decl * mk_num_decl(unsigned num_parameters, parameter const * parameters, unsigned arity);
|
||||
|
||||
public:
|
||||
arith_decl_plugin();
|
||||
|
||||
virtual ~arith_decl_plugin();
|
||||
virtual void finalize();
|
||||
|
||||
algebraic_numbers::manager & am();
|
||||
algebraic_numbers_wrapper & aw();
|
||||
|
||||
virtual void del(parameter const & p);
|
||||
virtual parameter translate(parameter const & p, decl_plugin & target);
|
||||
|
||||
virtual decl_plugin * mk_fresh() {
|
||||
return alloc(arith_decl_plugin);
|
||||
}
|
||||
|
||||
virtual sort * mk_sort(decl_kind k, unsigned num_parameters, parameter const * parameters);
|
||||
|
||||
virtual func_decl * mk_func_decl(decl_kind k, unsigned num_parameters, parameter const * parameters,
|
||||
unsigned arity, sort * const * domain, sort * range);
|
||||
|
||||
virtual func_decl * mk_func_decl(decl_kind k, unsigned num_parameters, parameter const * parameters,
|
||||
unsigned num_args, expr * const * args, sort * range);
|
||||
|
||||
virtual bool is_value(app* e) const;
|
||||
|
||||
virtual bool are_distinct(app* a, app* b) const;
|
||||
|
||||
virtual void get_op_names(svector<builtin_name> & op_names, symbol const & logic);
|
||||
|
||||
virtual void get_sort_names(svector<builtin_name> & sort_names, symbol const & logic);
|
||||
|
||||
app * mk_numeral(rational const & n, bool is_int);
|
||||
|
||||
app * mk_numeral(algebraic_numbers::anum const & val, bool is_int);
|
||||
|
||||
// Create a (real) numeral that is the i-th root of the polynomial encoded using the given sexpr.
|
||||
app * mk_numeral(sexpr const * p, unsigned i);
|
||||
|
||||
app * mk_pi() const { return m_pi; }
|
||||
|
||||
app * mk_e() const { return m_e; }
|
||||
|
||||
virtual expr * get_some_value(sort * s);
|
||||
|
||||
void set_cancel(bool f);
|
||||
};
|
||||
|
||||
class arith_util {
|
||||
ast_manager & m_manager;
|
||||
family_id m_afid;
|
||||
arith_decl_plugin * m_plugin;
|
||||
|
||||
void init_plugin();
|
||||
|
||||
arith_decl_plugin & plugin() const {
|
||||
if (!m_plugin) const_cast<arith_util*>(this)->init_plugin();
|
||||
SASSERT(m_plugin != 0);
|
||||
return *m_plugin;
|
||||
}
|
||||
|
||||
public:
|
||||
arith_util(ast_manager & m);
|
||||
|
||||
ast_manager & get_manager() const { return m_manager; }
|
||||
family_id get_family_id() const { return m_afid; }
|
||||
|
||||
algebraic_numbers::manager & am() {
|
||||
return plugin().am();
|
||||
}
|
||||
|
||||
bool is_arith_expr(expr const * n) const { return is_app(n) && to_app(n)->get_family_id() == m_afid; }
|
||||
bool is_numeral(expr const * n, rational & val, bool & is_int) const;
|
||||
bool is_numeral(expr const * n, rational & val) const { bool is_int; return is_numeral(n, val, is_int); }
|
||||
bool is_numeral(expr const * n) const { return is_app_of(n, m_afid, OP_NUM); }
|
||||
bool is_irrational_algebraic_numeral(expr const * n) const { return is_app_of(n, m_afid, OP_IRRATIONAL_ALGEBRAIC_NUM); }
|
||||
bool is_irrational_algebraic_numeral(expr const * n, algebraic_numbers::anum & val);
|
||||
algebraic_numbers::anum const & to_irrational_algebraic_numeral(expr const * n);
|
||||
bool is_zero(expr const * n) const { rational val; return is_numeral(n, val) && val.is_zero(); }
|
||||
bool is_minus_one(expr * n) const { rational tmp; return is_numeral(n, tmp) && tmp.is_minus_one(); }
|
||||
// return true if \c n is a term of the form (* -1 r)
|
||||
bool is_times_minus_one(expr * n, expr * & r) const {
|
||||
if (is_mul(n) && to_app(n)->get_num_args() == 2 && is_minus_one(to_app(n)->get_arg(0))) {
|
||||
r = to_app(n)->get_arg(1);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool is_le(expr const * n) const { return is_app_of(n, m_afid, OP_LE); }
|
||||
bool is_ge(expr const * n) const { return is_app_of(n, m_afid, OP_GE); }
|
||||
bool is_lt(expr const * n) const { return is_app_of(n, m_afid, OP_LT); }
|
||||
bool is_gt(expr const * n) const { return is_app_of(n, m_afid, OP_GT); }
|
||||
bool is_add(expr const * n) const { return is_app_of(n, m_afid, OP_ADD); }
|
||||
bool is_sub(expr const * n) const { return is_app_of(n, m_afid, OP_SUB); }
|
||||
bool is_uminus(expr const * n) const { return is_app_of(n, m_afid, OP_UMINUS); }
|
||||
bool is_mul(expr const * n) const { return is_app_of(n, m_afid, OP_MUL); }
|
||||
bool is_div(expr const * n) const { return is_app_of(n, m_afid, OP_DIV); }
|
||||
bool is_idiv(expr const * n) const { return is_app_of(n, m_afid, OP_IDIV); }
|
||||
bool is_mod(expr const * n) const { return is_app_of(n, m_afid, OP_MOD); }
|
||||
bool is_rem(expr const * n) const { return is_app_of(n, m_afid, OP_REM); }
|
||||
bool is_to_real(expr const * n) const { return is_app_of(n, m_afid, OP_TO_REAL); }
|
||||
bool is_to_int(expr const * n) const { return is_app_of(n, m_afid, OP_TO_INT); }
|
||||
bool is_is_int(expr const * n) const { return is_app_of(n, m_afid, OP_IS_INT); }
|
||||
bool is_power(expr const * n) const { return is_app_of(n, m_afid, OP_POWER); }
|
||||
|
||||
bool is_int(sort const * s) const { return is_sort_of(s, m_afid, INT_SORT); }
|
||||
bool is_int(expr const * n) const { return is_int(m_manager.get_sort(n)); }
|
||||
bool is_real(sort const * s) const { return is_sort_of(s, m_afid, REAL_SORT); }
|
||||
bool is_real(expr const * n) const { return is_real(m_manager.get_sort(n)); }
|
||||
bool is_int_real(sort const * s) const { return s->get_family_id() == m_afid; }
|
||||
bool is_int_real(expr const * n) const { return is_int_real(m_manager.get_sort(n)); }
|
||||
|
||||
MATCH_UNARY(is_uminus);
|
||||
|
||||
MATCH_BINARY(is_sub);
|
||||
MATCH_BINARY(is_add);
|
||||
MATCH_BINARY(is_mul);
|
||||
MATCH_BINARY(is_le);
|
||||
MATCH_BINARY(is_ge);
|
||||
MATCH_BINARY(is_lt);
|
||||
MATCH_BINARY(is_gt);
|
||||
MATCH_BINARY(is_mod);
|
||||
MATCH_BINARY(is_rem);
|
||||
MATCH_BINARY(is_div);
|
||||
MATCH_BINARY(is_idiv);
|
||||
|
||||
|
||||
sort * mk_int() { return m_manager.mk_sort(m_afid, INT_SORT); }
|
||||
sort * mk_real() { return m_manager.mk_sort(m_afid, REAL_SORT); }
|
||||
|
||||
app * mk_numeral(rational const & val, bool is_int) const {
|
||||
return plugin().mk_numeral(val, is_int);
|
||||
}
|
||||
app * mk_numeral(rational const & val, sort const * s) const {
|
||||
SASSERT(is_int(s) || is_real(s));
|
||||
return mk_numeral(val, is_int(s));
|
||||
}
|
||||
app * mk_numeral(algebraic_numbers::anum const & val, bool is_int) {
|
||||
return plugin().mk_numeral(val, is_int);
|
||||
}
|
||||
app * mk_numeral(sexpr const * p, unsigned i) {
|
||||
return plugin().mk_numeral(p, i);
|
||||
}
|
||||
app * mk_le(expr * arg1, expr * arg2) const { return m_manager.mk_app(m_afid, OP_LE, arg1, arg2); }
|
||||
app * mk_ge(expr * arg1, expr * arg2) const { return m_manager.mk_app(m_afid, OP_GE, arg1, arg2); }
|
||||
app * mk_lt(expr * arg1, expr * arg2) const { return m_manager.mk_app(m_afid, OP_LT, arg1, arg2); }
|
||||
app * mk_gt(expr * arg1, expr * arg2) const { return m_manager.mk_app(m_afid, OP_GT, arg1, arg2); }
|
||||
|
||||
app * mk_add(unsigned num_args, expr * const * args) { return m_manager.mk_app(m_afid, OP_ADD, num_args, args); }
|
||||
app * mk_add(expr * arg1, expr * arg2) { return m_manager.mk_app(m_afid, OP_ADD, arg1, arg2); }
|
||||
app * mk_add(expr * arg1, expr * arg2, expr* arg3) { return m_manager.mk_app(m_afid, OP_ADD, arg1, arg2, arg3); }
|
||||
|
||||
app * mk_sub(expr * arg1, expr * arg2) { return m_manager.mk_app(m_afid, OP_SUB, arg1, arg2); }
|
||||
app * mk_sub(unsigned num_args, expr * const * args) { return m_manager.mk_app(m_afid, OP_SUB, num_args, args); }
|
||||
app * mk_mul(expr * arg1, expr * arg2) { return m_manager.mk_app(m_afid, OP_MUL, arg1, arg2); }
|
||||
app * mk_mul(expr * arg1, expr * arg2, expr* arg3) { return m_manager.mk_app(m_afid, OP_MUL, arg1, arg2, arg3); }
|
||||
app * mk_mul(unsigned num_args, expr * const * args) { return m_manager.mk_app(m_afid, OP_MUL, num_args, args); }
|
||||
app * mk_uminus(expr * arg) { return m_manager.mk_app(m_afid, OP_UMINUS, arg); }
|
||||
app * mk_div(expr * arg1, expr * arg2) { return m_manager.mk_app(m_afid, OP_DIV, arg1, arg2); }
|
||||
app * mk_idiv(expr * arg1, expr * arg2) { return m_manager.mk_app(m_afid, OP_IDIV, arg1, arg2); }
|
||||
app * mk_rem(expr * arg1, expr * arg2) { return m_manager.mk_app(m_afid, OP_REM, arg1, arg2); }
|
||||
app * mk_mod(expr * arg1, expr * arg2) { return m_manager.mk_app(m_afid, OP_MOD, arg1, arg2); }
|
||||
app * mk_to_real(expr * arg1) { return m_manager.mk_app(m_afid, OP_TO_REAL, arg1); }
|
||||
app * mk_to_int(expr * arg1) { return m_manager.mk_app(m_afid, OP_TO_INT, arg1); }
|
||||
app * mk_is_int(expr * arg1) { return m_manager.mk_app(m_afid, OP_IS_INT, arg1); }
|
||||
app * mk_power(expr* arg1, expr* arg2) { return m_manager.mk_app(m_afid, OP_POWER, arg1, arg2); }
|
||||
|
||||
app * mk_sin(expr * arg) { return m_manager.mk_app(m_afid, OP_SIN, arg); }
|
||||
app * mk_cos(expr * arg) { return m_manager.mk_app(m_afid, OP_COS, arg); }
|
||||
app * mk_tan(expr * arg) { return m_manager.mk_app(m_afid, OP_TAN, arg); }
|
||||
app * mk_asin(expr * arg) { return m_manager.mk_app(m_afid, OP_ASIN, arg); }
|
||||
app * mk_acos(expr * arg) { return m_manager.mk_app(m_afid, OP_ACOS, arg); }
|
||||
app * mk_atan(expr * arg) { return m_manager.mk_app(m_afid, OP_ATAN, arg); }
|
||||
|
||||
app * mk_sinh(expr * arg) { return m_manager.mk_app(m_afid, OP_SINH, arg); }
|
||||
app * mk_cosh(expr * arg) { return m_manager.mk_app(m_afid, OP_COSH, arg); }
|
||||
app * mk_tanh(expr * arg) { return m_manager.mk_app(m_afid, OP_TANH, arg); }
|
||||
app * mk_asinh(expr * arg) { return m_manager.mk_app(m_afid, OP_ASINH, arg); }
|
||||
app * mk_acosh(expr * arg) { return m_manager.mk_app(m_afid, OP_ACOSH, arg); }
|
||||
app * mk_atanh(expr * arg) { return m_manager.mk_app(m_afid, OP_ATANH, arg); }
|
||||
|
||||
bool is_pi(expr * arg) { return is_app_of(arg, m_afid, OP_PI); }
|
||||
bool is_e(expr * arg) { return is_app_of(arg, m_afid, OP_E); }
|
||||
|
||||
app * mk_pi() { return plugin().mk_pi(); }
|
||||
app * mk_e() { return plugin().mk_e(); }
|
||||
|
||||
/**
|
||||
\brief Return the equality (= lhs rhs), but it makes sure that
|
||||
if one of the arguments is a numeral, then it will be in the right-hand-side;
|
||||
if none of them are numerals, then the left-hand-side has a smaller id than the right hand side.
|
||||
*/
|
||||
app * mk_eq(expr * lhs, expr * rhs) {
|
||||
if (is_numeral(lhs) || (!is_numeral(rhs) && lhs->get_id() > rhs->get_id()))
|
||||
std::swap(lhs, rhs);
|
||||
if (lhs == rhs)
|
||||
return m_manager.mk_true();
|
||||
if (is_numeral(lhs) && is_numeral(rhs)) {
|
||||
SASSERT(lhs != rhs);
|
||||
return m_manager.mk_false();
|
||||
}
|
||||
return m_manager.mk_eq(lhs, rhs);
|
||||
}
|
||||
|
||||
void set_cancel(bool f) {
|
||||
plugin().set_cancel(f);
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* _ARITH_DECL_PLUGIN_H_ */
|
||||
|
316
lib/arith_eq_adapter.cpp
Normal file
316
lib/arith_eq_adapter.cpp
Normal file
|
@ -0,0 +1,316 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
arith_eq_adapter.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
<abstract>
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-05-25.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#include"smt_context.h"
|
||||
#include"arith_eq_adapter.h"
|
||||
#include"ast_pp.h"
|
||||
#include"ast_ll_pp.h"
|
||||
#include"stats.h"
|
||||
#include"simplifier.h"
|
||||
#include"ast_smt2_pp.h"
|
||||
|
||||
namespace smt {
|
||||
|
||||
class already_processed_trail : public trail<context> {
|
||||
// Remark: it is safer to use a trail object, because it guarantees that the enodes
|
||||
// are still alive when the undo operation is performed.
|
||||
//
|
||||
// If a local backtracking stack is used in the class arith_eq_adapter is used,
|
||||
// then we cannot guarantee that.
|
||||
arith_eq_adapter::already_processed & m_already_processed;
|
||||
enode * m_n1;
|
||||
enode * m_n2;
|
||||
public:
|
||||
already_processed_trail(arith_eq_adapter::already_processed & m, enode * n1, enode * n2):
|
||||
m_already_processed(m),
|
||||
m_n1(n1),
|
||||
m_n2(n2) {
|
||||
}
|
||||
|
||||
virtual void undo(context & ctx) {
|
||||
m_already_processed.erase(m_n1, m_n2);
|
||||
TRACE("arith_eq_adapter_profile", tout << "del #" << m_n1->get_owner_id() << " #" << m_n2->get_owner_id() << "\n";);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
\brief The atoms m_eq, m_le, and m_ge should be marked as relevant only after
|
||||
m_n1 and m_n2 are marked as relevant.
|
||||
*/
|
||||
class arith_eq_relevancy_eh : public relevancy_eh {
|
||||
expr * m_n1;
|
||||
expr * m_n2;
|
||||
expr * m_eq;
|
||||
expr * m_le;
|
||||
expr * m_ge;
|
||||
public:
|
||||
arith_eq_relevancy_eh(expr * n1, expr * n2, expr * eq, expr * le, expr * ge):
|
||||
m_n1(n1),
|
||||
m_n2(n2),
|
||||
m_eq(eq),
|
||||
m_le(le),
|
||||
m_ge(ge) {
|
||||
}
|
||||
|
||||
virtual ~arith_eq_relevancy_eh() {}
|
||||
|
||||
virtual void operator()(relevancy_propagator & rp) {
|
||||
if (!rp.is_relevant(m_n1))
|
||||
return;
|
||||
if (!rp.is_relevant(m_n2))
|
||||
return;
|
||||
rp.mark_as_relevant(m_eq);
|
||||
rp.mark_as_relevant(m_le);
|
||||
rp.mark_as_relevant(m_ge);
|
||||
}
|
||||
};
|
||||
|
||||
arith_simplifier_plugin * arith_eq_adapter::get_simplifier() {
|
||||
if (!m_as) {
|
||||
simplifier & s = get_context().get_simplifier();
|
||||
m_as = static_cast<arith_simplifier_plugin*>(s.get_plugin(m_owner.get_family_id()));
|
||||
}
|
||||
return m_as;
|
||||
}
|
||||
|
||||
void arith_eq_adapter::mk_axioms(enode * n1, enode * n2) {
|
||||
SASSERT(n1 != n2);
|
||||
ast_manager & m = get_manager();
|
||||
TRACE("arith_eq_adapter_mk_axioms", tout << "#" << n1->get_owner_id() << " #" << n2->get_owner_id() << "\n";
|
||||
tout << mk_ismt2_pp(n1->get_owner(), m) << "\n" << mk_ismt2_pp(n2->get_owner(), m) << "\n";);
|
||||
if (n1->get_owner_id() > n2->get_owner_id())
|
||||
std::swap(n1, n2);
|
||||
app * t1 = n1->get_owner();
|
||||
app * t2 = n2->get_owner();
|
||||
if (m.is_value(t1) && m.is_value(t2)) {
|
||||
// Nothing to be done
|
||||
// We don't need to create axioms for 2 = 3
|
||||
return;
|
||||
}
|
||||
|
||||
context & ctx = get_context();
|
||||
CTRACE("arith_eq_adapter_relevancy", !(ctx.is_relevant(n1) && ctx.is_relevant(n2)),
|
||||
tout << "is_relevant(n1): #" << n1->get_owner_id() << " " << ctx.is_relevant(n1) << "\n";
|
||||
tout << "is_relevant(n2): #" << n2->get_owner_id() << " " << ctx.is_relevant(n2) << "\n";
|
||||
tout << mk_pp(n1->get_owner(), get_manager()) << "\n";
|
||||
tout << mk_pp(n2->get_owner(), get_manager()) << "\n";
|
||||
ctx.display(tout););
|
||||
//
|
||||
// The atoms d.m_t1_eq_t2, d.m_le, and d.m_ge should only be marked as relevant
|
||||
// after n1 and n2 are marked as relevant.
|
||||
//
|
||||
data d;
|
||||
if (m_already_processed.find(n1, n2, d))
|
||||
return;
|
||||
|
||||
TRACE("arith_eq_adapter_profile", tout << "mk #" << n1->get_owner_id() << " #" << n2->get_owner_id() << " " <<
|
||||
m_already_processed.size() << " " << ctx.get_scope_level() << "\n";);
|
||||
|
||||
m_stats.m_num_eq_axioms++;
|
||||
|
||||
TRACE("arith_eq_adapter_profile_detail",
|
||||
tout << "mk_detail " << mk_bounded_pp(n1->get_owner(), m, 5) << " " <<
|
||||
mk_bounded_pp(n2->get_owner(), m, 5) << "\n";);
|
||||
|
||||
app_ref t1_eq_t2(m);
|
||||
|
||||
t1_eq_t2 = ctx.mk_eq_atom(t1, t2);
|
||||
SASSERT(!m.is_false(t1_eq_t2));
|
||||
|
||||
TRACE("arith_eq_adapter_bug", tout << mk_bounded_pp(t1_eq_t2, m) << "\n"
|
||||
<< mk_bounded_pp(t1, m) << "\n"
|
||||
<< mk_bounded_pp(t2, m) << "\n";);
|
||||
|
||||
// UNRESOLVED ISSUE:
|
||||
//
|
||||
// arith_eq_adapter is still creating problems.
|
||||
// The following disabled code fixes the issues, but create performance problems.
|
||||
// The alternative does not works 100%. It generates problems when the literal
|
||||
// created by the adapter during the search is included in a learned clause.
|
||||
// Here is a sequence of events that triggers a crash:
|
||||
// 1) The terms t1 >= t2 and t1 <= t2 are not in simplified form.
|
||||
// For example, let us assume t1 := (* -1 x) and t2 := x.
|
||||
// Since, t1 and t2 were internalized at this point, the following code works.
|
||||
// That is the arith internalizer accepts the formula (+ (* -1 x) (* -1 x))
|
||||
// that is not in simplified form. Let s be the term (+ (* -1 x) (* -1 x))
|
||||
// 2) Assume now that a conflict is detected a lemma containing s is created.
|
||||
// 3) The enodes associated with t1, t2 and s are destroyed during backtracking.
|
||||
// 4) The term s is reinternalized at smt::context::reinit_clauses. Term t2 is
|
||||
// also reinitialized, but t1 is not. We only create a "name" for a term (* -1 x)
|
||||
// if it is embedded in a function application.
|
||||
// 5) theory_arith fails to internalize (+ (* -1 x) (* -1 x)), and Z3 crashes.
|
||||
//
|
||||
|
||||
#if 0
|
||||
// This block of code uses the simplifier for creating the literals t1 >= t2 and t1 <= t2.
|
||||
// It has serious performance problems in VCC benchmarks.
|
||||
// The problem seems to be the following:
|
||||
// t1 and t2 are slacks (i.e., names for linear polynomials).
|
||||
// The simplifier will create inequalities that will indirectly imply that t1 >= t2 and t1 <= t2.
|
||||
// Example if: t1 := 1 + a
|
||||
// t2 := 2 + b
|
||||
// the simplifier will create
|
||||
// a - b >= -1
|
||||
// a - b <= -1
|
||||
// These inequalities imply that 1+a >= 2+b and 1+a <= 2+b,
|
||||
// but the tableau is complete different.
|
||||
|
||||
|
||||
// BTW, note that we don't really need to handle the is_numeral case when using
|
||||
// the simplifier. However, doing that, it seems we minimize the performance problem.
|
||||
expr_ref le(m);
|
||||
expr_ref ge(m);
|
||||
if (m_util.is_numeral(t1))
|
||||
std::swap(t1, t2);
|
||||
if (m_util.is_numeral(t2)) {
|
||||
le = m_util.mk_le(t1, t2);
|
||||
ge = m_util.mk_ge(t1, t2);
|
||||
}
|
||||
else {
|
||||
arith_simplifier_plugin & s = *(get_simplifier());
|
||||
s.mk_le(t1, t2, le);
|
||||
s.mk_ge(t1, t2, ge);
|
||||
}
|
||||
TRACE("arith_eq_adapter_perf", tout << mk_ismt2_pp(t1_eq_t2, m) << "\n" << mk_ismt2_pp(le, m) << "\n" << mk_ismt2_pp(ge, m) << "\n";);
|
||||
#else
|
||||
// Old version that used to be buggy.
|
||||
// I fixed the theory arithmetic internalizer to accept non simplified terms of the form t1 - t2
|
||||
// if t1 and t2 already have slacks (theory variables) associated with them.
|
||||
app * le = 0;
|
||||
app * ge = 0;
|
||||
if (m_util.is_numeral(t1))
|
||||
std::swap(t1, t2);
|
||||
if (m_util.is_numeral(t2)) {
|
||||
le = m_util.mk_le(t1, t2);
|
||||
ge = m_util.mk_ge(t1, t2);
|
||||
}
|
||||
else {
|
||||
sort * st = m.get_sort(t1);
|
||||
app * minus_one = m_util.mk_numeral(rational::minus_one(), st);
|
||||
app * zero = m_util.mk_numeral(rational::zero(), st);
|
||||
app_ref s(m_util.mk_add(t1, m_util.mk_mul(minus_one, t2)), m);
|
||||
le = m_util.mk_le(s, zero);
|
||||
ge = m_util.mk_ge(s, zero);
|
||||
}
|
||||
TRACE("arith_eq_adapter_perf",
|
||||
tout << mk_ismt2_pp(t1_eq_t2, m) << "\n" << mk_ismt2_pp(le, m) << "\n" << mk_ismt2_pp(ge, m) << "\n";);
|
||||
#endif
|
||||
|
||||
ctx.push_trail(already_processed_trail(m_already_processed, n1, n2));
|
||||
m_already_processed.insert(n1, n2, data(t1_eq_t2, le, ge));
|
||||
TRACE("arith_eq_adapter_profile", tout << "insert #" << n1->get_owner_id() << " #" << n2->get_owner_id() << "\n";);
|
||||
ctx.internalize(t1_eq_t2, true);
|
||||
literal t1_eq_t2_lit(ctx.get_bool_var(t1_eq_t2));
|
||||
TRACE("interface_eq",
|
||||
tout << "core should try true phase first for the equality: " << t1_eq_t2_lit << "\n";
|
||||
tout << "#" << n1->get_owner_id() << " == #" << n2->get_owner_id() << "\n";
|
||||
tout << "try_true_first: " << ctx.try_true_first(t1_eq_t2_lit.var()) << "\n";);
|
||||
TRACE("arith_eq_adapter_bug",
|
||||
tout << "le: " << mk_ismt2_pp(le, m) << "\nge: " << mk_ismt2_pp(ge, m) << "\n";);
|
||||
ctx.internalize(le, true);
|
||||
ctx.internalize(ge, true);
|
||||
SASSERT(ctx.lit_internalized(le));
|
||||
SASSERT(ctx.lit_internalized(ge));
|
||||
literal le_lit = ctx.get_literal(le);
|
||||
literal ge_lit = ctx.get_literal(ge);
|
||||
if (ctx.try_true_first(t1_eq_t2_lit.var())) {
|
||||
// Remark: I need to propagate the try_true_first flag to the auxiliary atom le_lit and ge_lit.
|
||||
// Otherwise model based theory combination will be ineffective, because if the core
|
||||
// case splits in le_lit and ge_lit before t1_eq_t2_lit it will essentially assign an arbitrary phase to t1_eq_t2_lit.
|
||||
ctx.set_true_first_flag(le_lit.var());
|
||||
ctx.set_true_first_flag(ge_lit.var());
|
||||
}
|
||||
theory_id tid = m_owner.get_id();
|
||||
if (m.proofs_enabled() && m_proof_hint.empty()) {
|
||||
m_proof_hint.push_back(parameter(symbol("triangle-eq")));
|
||||
}
|
||||
ctx.mk_th_axiom(tid, ~t1_eq_t2_lit, le_lit, m_proof_hint.size(), m_proof_hint.c_ptr());
|
||||
ctx.mk_th_axiom(tid, ~t1_eq_t2_lit, ge_lit, m_proof_hint.size(), m_proof_hint.c_ptr());
|
||||
ctx.mk_th_axiom(tid, t1_eq_t2_lit, ~le_lit, ~ge_lit, m_proof_hint.size(), m_proof_hint.c_ptr());
|
||||
TRACE("arith_eq_adapter", tout << "internalizing: "
|
||||
<< " " << mk_pp(le, m) << ": " << le_lit
|
||||
<< " " << mk_pp(ge, m) << ": " << ge_lit
|
||||
<< " " << mk_pp(t1_eq_t2, m) << ": " << t1_eq_t2_lit << "\n";);
|
||||
|
||||
if (m_params.m_arith_add_binary_bounds) {
|
||||
TRACE("arith_eq_adapter", tout << "adding binary bounds...\n";);
|
||||
ctx.mk_th_axiom(tid, le_lit, ge_lit, 3, m_proof_hint.c_ptr());
|
||||
}
|
||||
if (ctx.relevancy()) {
|
||||
relevancy_eh * eh = ctx.mk_relevancy_eh(arith_eq_relevancy_eh(n1->get_owner(), n2->get_owner(), t1_eq_t2, le, ge));
|
||||
ctx.add_relevancy_eh(n1->get_owner(), eh);
|
||||
ctx.add_relevancy_eh(n2->get_owner(), eh);
|
||||
}
|
||||
if (!m_params.m_arith_lazy_adapter && !ctx.at_base_level() &&
|
||||
n1->get_iscope_lvl() <= ctx.get_base_level() && n2->get_iscope_lvl() <= ctx.get_base_level()) {
|
||||
m_restart_pairs.push_back(enode_pair(n1, n2));
|
||||
}
|
||||
TRACE("arith_eq_adapter_detail", ctx.display(tout););
|
||||
}
|
||||
|
||||
void arith_eq_adapter::new_eq_eh(theory_var v1, theory_var v2) {
|
||||
TRACE("arith_eq_adapter", tout << "v" << v1 << " = v" << v2 << " #" << get_enode(v1)->get_owner_id() << " = #" << get_enode(v2)->get_owner_id() << "\n";);
|
||||
TRACE("arith_eq_adapter_bug", tout << mk_bounded_pp(get_enode(v1)->get_owner(), get_manager()) << "\n" << mk_bounded_pp(get_enode(v2)->get_owner(), get_manager()) << "\n";);
|
||||
mk_axioms(get_enode(v1), get_enode(v2));
|
||||
}
|
||||
|
||||
void arith_eq_adapter::new_diseq_eh(theory_var v1, theory_var v2) {
|
||||
TRACE("arith_eq_adapter", tout << "v" << v1 << " != v" << v2 << " #" << get_enode(v1)->get_owner_id() << " != #" << get_enode(v2)->get_owner_id() << "\n";);
|
||||
mk_axioms(get_enode(v1), get_enode(v2));
|
||||
}
|
||||
|
||||
void arith_eq_adapter::init_search_eh() {
|
||||
m_restart_pairs.reset();
|
||||
}
|
||||
|
||||
void arith_eq_adapter::reset_eh() {
|
||||
TRACE("arith_eq_adapter", tout << "reset\n";);
|
||||
m_already_processed .reset();
|
||||
m_restart_pairs .reset();
|
||||
m_stats .reset();
|
||||
}
|
||||
|
||||
void arith_eq_adapter::restart_eh() {
|
||||
TRACE("arith_eq_adapter", tout << "restart\n";);
|
||||
svector<enode_pair> tmp(m_restart_pairs);
|
||||
svector<enode_pair>::iterator it = tmp.begin();
|
||||
svector<enode_pair>::iterator end = tmp.end();
|
||||
m_restart_pairs.reset();
|
||||
for (; it != end; ++it) {
|
||||
TRACE("arith_eq_adapter", tout << "creating arith_eq_adapter axioms at the base level #" << it->first->get_owner_id() << " #" <<
|
||||
it->second->get_owner_id() << "\n";);
|
||||
mk_axioms(it->first, it->second);
|
||||
}
|
||||
}
|
||||
|
||||
void arith_eq_adapter::collect_statistics(::statistics & st) const {
|
||||
st.update("eq adapter", m_stats.m_num_eq_axioms);
|
||||
}
|
||||
|
||||
void arith_eq_adapter::display_already_processed(std::ostream & out) const {
|
||||
obj_pair_map<enode, enode, data>::iterator it = m_already_processed.begin();
|
||||
obj_pair_map<enode, enode, data>::iterator end = m_already_processed.end();
|
||||
for (; it != end; ++it) {
|
||||
enode * n1 = it->get_key1();
|
||||
enode * n2 = it->get_key2();
|
||||
out << "eq_adapter: #" << n1->get_owner_id() << " #" << n2->get_owner_id() << "\n";
|
||||
}
|
||||
}
|
||||
};
|
||||
|
97
lib/arith_eq_adapter.h
Normal file
97
lib/arith_eq_adapter.h
Normal file
|
@ -0,0 +1,97 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
arith_eq_adapter.h
|
||||
|
||||
Abstract:
|
||||
|
||||
<abstract>
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-05-25.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _ARITH_EQ_ADAPTER_H_
|
||||
#define _ARITH_EQ_ADAPTER_H_
|
||||
|
||||
#include"smt_theory.h"
|
||||
#include"obj_pair_hashtable.h"
|
||||
#include"arith_decl_plugin.h"
|
||||
#include"statistics.h"
|
||||
#include"arith_simplifier_plugin.h"
|
||||
|
||||
namespace smt {
|
||||
|
||||
struct arith_eq_adapter_stats {
|
||||
unsigned m_num_eq_axioms;
|
||||
void reset() { m_num_eq_axioms = 0; }
|
||||
arith_eq_adapter_stats() { reset(); }
|
||||
};
|
||||
|
||||
/**
|
||||
\brief Auxiliary class used to convert (dis) equalities
|
||||
propagated from the core into arith equalities/inequalities
|
||||
atoms. This class is used by the arithmetic theories to
|
||||
handle the (dis) equalities propagated from the logical context.
|
||||
|
||||
- config 1:
|
||||
recreate axioms at restart
|
||||
|
||||
- config 2:
|
||||
lazy diseq split
|
||||
*/
|
||||
class arith_eq_adapter {
|
||||
public:
|
||||
arith_eq_adapter_stats m_stats;
|
||||
|
||||
private:
|
||||
struct data {
|
||||
expr * m_t1_eq_t2;
|
||||
expr * m_le;
|
||||
expr * m_ge;
|
||||
data():m_t1_eq_t2(0), m_le(0), m_ge(0) {}
|
||||
data(expr * t1_eq_t2, expr * le, expr * ge):m_t1_eq_t2(t1_eq_t2), m_le(le), m_ge(ge) {}
|
||||
};
|
||||
|
||||
public:
|
||||
typedef obj_pair_map<enode, enode, data> already_processed;
|
||||
|
||||
private:
|
||||
theory & m_owner;
|
||||
theory_arith_params & m_params;
|
||||
arith_util & m_util;
|
||||
arith_simplifier_plugin * m_as;
|
||||
|
||||
already_processed m_already_processed;
|
||||
svector<enode_pair> m_restart_pairs;
|
||||
svector<parameter> m_proof_hint;
|
||||
|
||||
context & get_context() const { return m_owner.get_context(); }
|
||||
ast_manager & get_manager() const { return m_owner.get_manager(); }
|
||||
enode * get_enode(theory_var v) const { return m_owner.get_enode(v); }
|
||||
|
||||
arith_simplifier_plugin * get_simplifier();
|
||||
|
||||
public:
|
||||
arith_eq_adapter(theory & owner, theory_arith_params & params, arith_util & u):m_owner(owner), m_params(params), m_util(u), m_as(0) {}
|
||||
void new_eq_eh(theory_var v1, theory_var v2);
|
||||
void new_diseq_eh(theory_var v1, theory_var v2);
|
||||
void reset_eh();
|
||||
void init_search_eh();
|
||||
void restart_eh();
|
||||
/**
|
||||
\brief Add the eq axioms for n1 and n2.
|
||||
*/
|
||||
void mk_axioms(enode * n1, enode * n2);
|
||||
void collect_statistics(::statistics & st) const;
|
||||
void display_already_processed(std::ostream & out) const;
|
||||
};
|
||||
};
|
||||
|
||||
#endif /* _ARITH_EQ_ADAPTER_H_ */
|
||||
|
632
lib/arith_eq_solver.cpp
Normal file
632
lib/arith_eq_solver.cpp
Normal file
|
@ -0,0 +1,632 @@
|
|||
/*++
|
||||
Copyright (c) 2007 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
arith_eq_solver.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Solver for linear arithmetic equalities.
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2012-02-25
|
||||
|
||||
--*/
|
||||
#include"arith_eq_solver.h"
|
||||
|
||||
|
||||
arith_eq_solver::~arith_eq_solver() {
|
||||
}
|
||||
|
||||
arith_eq_solver::arith_eq_solver(ast_manager & m, params_ref const& p):
|
||||
m(m),
|
||||
m_params(p),
|
||||
m_util(m),
|
||||
m_arith_rewriter(m)
|
||||
{
|
||||
m_params.set_bool(":gcd-rounding", true);
|
||||
// m_params.set_bool(":sum", true);
|
||||
m_arith_rewriter.updt_params(m_params);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief Return true if the first monomial of t is negative.
|
||||
*/
|
||||
bool arith_eq_solver::is_neg_poly(expr * t) const {
|
||||
if (m_util.is_add(t)) {
|
||||
t = to_app(t)->get_arg(0);
|
||||
}
|
||||
if (m_util.is_mul(t)) {
|
||||
t = to_app(t)->get_arg(0);
|
||||
rational r;
|
||||
bool is_int;
|
||||
if (m_util.is_numeral(t, r, is_int))
|
||||
return r.is_neg();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void arith_eq_solver::prop_mod_const(expr * e, unsigned depth, numeral const& k, expr_ref& result) {
|
||||
SASSERT(m_util.is_int(e));
|
||||
SASSERT(k.is_int() && k.is_pos());
|
||||
numeral n;
|
||||
bool is_int;
|
||||
|
||||
if (depth == 0) {
|
||||
result = e;
|
||||
}
|
||||
else if (m_util.is_add(e) || m_util.is_mul(e)) {
|
||||
expr_ref_vector args(m);
|
||||
expr_ref tmp(m);
|
||||
app* a = to_app(e);
|
||||
for (unsigned i = 0; i < a->get_num_args(); ++i) {
|
||||
prop_mod_const(a->get_arg(i), depth - 1, k, tmp);
|
||||
args.push_back(tmp);
|
||||
}
|
||||
m_arith_rewriter.mk_app(a->get_decl(), args.size(), args.c_ptr(), result);
|
||||
}
|
||||
else if (m_util.is_numeral(e, n, is_int) && is_int) {
|
||||
result = m_util.mk_numeral(mod(n, k), true);
|
||||
}
|
||||
else {
|
||||
result = e;
|
||||
}
|
||||
}
|
||||
|
||||
void arith_eq_solver::gcd_normalize(vector<numeral>& values) {
|
||||
numeral g(0);
|
||||
for (unsigned i = 0; !g.is_one() && i < values.size(); ++i) {
|
||||
SASSERT(values[i].is_int());
|
||||
if (!values[i].is_zero()) {
|
||||
if (g.is_zero()) {
|
||||
g = abs(values[i]);
|
||||
}
|
||||
else {
|
||||
g = gcd(abs(values[i]), g);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (g.is_zero() || g.is_one()) {
|
||||
return;
|
||||
}
|
||||
for (unsigned i = 0; i < values.size(); ++i) {
|
||||
values[i] = values[i] / g;
|
||||
SASSERT(values[i].is_int());
|
||||
}
|
||||
}
|
||||
|
||||
unsigned arith_eq_solver::find_abs_min(vector<numeral>& values) {
|
||||
SASSERT(values.size() >= 2);
|
||||
unsigned index = 0;
|
||||
numeral v(0);
|
||||
for (unsigned i = 1; i < values.size(); ++i) {
|
||||
numeral w = abs(values[i]);
|
||||
if (v.is_zero() || (!w.is_zero() && w < v)) {
|
||||
index = i;
|
||||
v = w;
|
||||
}
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
static void print_row(std::ostream& out, vector<rational> const& row) {
|
||||
for(unsigned i = 0; i < row.size(); ++i) {
|
||||
out << row[i] << " ";
|
||||
}
|
||||
out << "\n";
|
||||
}
|
||||
|
||||
static void print_rows(std::ostream& out, vector<vector<rational> > const& rows) {
|
||||
for (unsigned i = 0; i < rows.size(); ++i) {
|
||||
print_row(out, rows[i]);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// The gcd of the coefficients to variables have to divide the
|
||||
// coefficient to the constant.
|
||||
// The constant is the last value in the array.
|
||||
//
|
||||
bool arith_eq_solver::gcd_test(vector<numeral>& values) {
|
||||
SASSERT(values.size() > 0);
|
||||
numeral g(0);
|
||||
numeral first_value = values[0];
|
||||
for (unsigned i = 1; !g.is_one() && i < values.size(); ++i) {
|
||||
if (!values[i].is_zero()) {
|
||||
if (g.is_zero()) {
|
||||
g = abs(values[i]);
|
||||
}
|
||||
else {
|
||||
g = gcd(abs(values[i]), g);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (g.is_one()) {
|
||||
return true;
|
||||
}
|
||||
if (g.is_zero()) {
|
||||
return first_value.is_zero();
|
||||
}
|
||||
numeral r = first_value/g;
|
||||
return r.is_int();
|
||||
}
|
||||
|
||||
|
||||
bool arith_eq_solver::solve_integer_equation(
|
||||
vector<numeral>& values,
|
||||
unsigned& index,
|
||||
bool& is_fresh
|
||||
)
|
||||
{
|
||||
TRACE("arith_eq_solver",
|
||||
tout << "solving: ";
|
||||
print_row(tout, values);
|
||||
);
|
||||
//
|
||||
// perform one step of the omega test equality elimination.
|
||||
//
|
||||
// Given:
|
||||
// a1*x1 + a2*x2 + .. + a_n*x_n + a_{n+1} = 0
|
||||
//
|
||||
// Assume gcd(a1,..,a_n,a_{n+1}) = 1
|
||||
// Assume gcd(a1,...,a_n) divides a_{n+1} (eg. gcd(a1,..,an) = 1)
|
||||
//
|
||||
// post-condition: values[index] = -1.
|
||||
//
|
||||
// Let a_index be index of least absolute value.
|
||||
//
|
||||
// If |a_index| = 1, then return row and index.
|
||||
// Otherwise:
|
||||
// Let m = |a_index| + 1
|
||||
// Set
|
||||
//
|
||||
// m*x_index'
|
||||
// =
|
||||
// ((a1 mod_hat m)*x1 + (a2 mod_hat m)*x2 + .. + (a_n mod_hat m)*x_n + (k mod_hat m))
|
||||
// =
|
||||
// (a1'*x1 + a2'*x2 + .. (-)1*x_index + ...)
|
||||
//
|
||||
// <=> Normalize signs so that sign to x_index is -1.
|
||||
// (-)a1'*x1 + (-)a2'*x2 + .. -1*x_index + ... + m*x_index' = 0
|
||||
//
|
||||
// Return row, where the coefficient to x_index is implicit.
|
||||
// Instead used the coefficient 'm' at position 'index'.
|
||||
//
|
||||
|
||||
gcd_normalize(values);
|
||||
if (!gcd_test(values)) {
|
||||
TRACE("arith_eq_solver", tout << "not sat\n";
|
||||
print_row(tout, values););
|
||||
return false;
|
||||
}
|
||||
index = find_abs_min(values);
|
||||
SASSERT(1 <= index && index < values.size());
|
||||
numeral a = values[index];
|
||||
numeral abs_a = abs(a);
|
||||
|
||||
if (abs_a.is_zero()) {
|
||||
// The equation is trivial.
|
||||
return true;
|
||||
}
|
||||
if (a.is_one()) {
|
||||
for (unsigned i = 0; i < values.size(); ++i) {
|
||||
values[i].neg();
|
||||
}
|
||||
}
|
||||
is_fresh = !abs_a.is_one();
|
||||
|
||||
if (is_fresh) {
|
||||
|
||||
numeral m = abs_a + numeral(1);
|
||||
for (unsigned i = 0; i < values.size(); ++i) {
|
||||
values[i] = mod_hat(values[i], m);
|
||||
}
|
||||
if (values[index].is_one()) {
|
||||
for (unsigned i = 0; i < values.size(); ++i) {
|
||||
values[i].neg();
|
||||
}
|
||||
}
|
||||
SASSERT(values[index].is_minus_one());
|
||||
values[index] = m;
|
||||
}
|
||||
|
||||
TRACE("arith_eq_solver",
|
||||
tout << "solved at index " << index << ": ";
|
||||
print_row(tout, values);
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void arith_eq_solver::substitute(
|
||||
row& r,
|
||||
row const& s,
|
||||
unsigned index
|
||||
)
|
||||
{
|
||||
SASSERT(1 <= index && index < s.size());
|
||||
TRACE("arith_eq_solver",
|
||||
tout << "substitute " << index << ":\n";
|
||||
print_row(tout, r);
|
||||
print_row(tout, s);
|
||||
);
|
||||
|
||||
if (index >= r.size()) {
|
||||
return;
|
||||
}
|
||||
|
||||
numeral c = r[index];
|
||||
if (c.is_zero()) {
|
||||
// no-op
|
||||
}
|
||||
else if (abs(s[index]).is_one()) {
|
||||
//
|
||||
// s encodes an equation that contains a variable
|
||||
// with a unit coefficient.
|
||||
//
|
||||
// Let
|
||||
// c = r[index]
|
||||
// s = s[index]*x + s'*y = 0
|
||||
// r = c*x + r'*y = 0
|
||||
//
|
||||
// =>
|
||||
//
|
||||
// 0
|
||||
// =
|
||||
// -sign(s[index])*c*s + r
|
||||
// =
|
||||
// -s[index]*sign(s[index])*c*x - sign(s[index])*c*s'*y + c*x + r'*y
|
||||
// =
|
||||
// -c*x - sign(s[index])*c*s'*y + c*x + r'*y
|
||||
// =
|
||||
// -sign(s[index])*c*s'*y + r'*y
|
||||
//
|
||||
numeral sign_s = s[index].is_pos()?numeral(1):numeral(-1);
|
||||
for (unsigned i = 0; i < r.size(); ++i) {
|
||||
r[i] -= c*sign_s*s[i];
|
||||
}
|
||||
for (unsigned i = r.size(); i < s.size(); ++i) {
|
||||
r.push_back(-c*sign_s*s[i]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
//
|
||||
// s encodes a substitution using an auxiliary variable.
|
||||
// the auxiliary variable is at position 'index'.
|
||||
//
|
||||
// Let
|
||||
// c = r[index]
|
||||
// s = s[index]*x + s'*y = 0
|
||||
// r = c*x + r'*y = 0
|
||||
//
|
||||
// s encodes : x |-> s[index]*x' + s'*y
|
||||
//
|
||||
// Set:
|
||||
//
|
||||
// r := c*s + r'*y
|
||||
//
|
||||
r[index] = numeral(0);
|
||||
for (unsigned i = 0; i < r.size(); ++i) {
|
||||
r[i] += c*s[i];
|
||||
}
|
||||
for (unsigned i = r.size(); i < s.size(); ++i) {
|
||||
r.push_back(c*s[i]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
TRACE("arith_eq_solver",
|
||||
tout << "result: ";
|
||||
print_row(tout, r);
|
||||
);
|
||||
}
|
||||
|
||||
bool arith_eq_solver::solve_integer_equations(
|
||||
vector<row>& rows,
|
||||
row& unsat_row
|
||||
)
|
||||
{
|
||||
// return solve_integer_equations_units(rows, unsat_row);
|
||||
return solve_integer_equations_gcd(rows, unsat_row);
|
||||
}
|
||||
|
||||
//
|
||||
// Naive integer equation solver where only units are eliminated.
|
||||
//
|
||||
|
||||
bool arith_eq_solver::solve_integer_equations_units(
|
||||
vector<row>& rows,
|
||||
row& unsat_row
|
||||
)
|
||||
{
|
||||
|
||||
TRACE("arith_eq_solver", print_rows(tout << "solving:\n", rows););
|
||||
|
||||
unsigned_vector todo, done;
|
||||
|
||||
for (unsigned i = 0; i < rows.size(); ++i) {
|
||||
todo.push_back(i);
|
||||
row& r = rows[i];
|
||||
gcd_normalize(r);
|
||||
if (!gcd_test(r)) {
|
||||
unsat_row = r;
|
||||
TRACE("arith_eq_solver", print_row(tout << "input is unsat: ", unsat_row); );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (unsigned i = 0; i < todo.size(); ++i) {
|
||||
row& r = rows[todo[i]];
|
||||
gcd_normalize(r);
|
||||
if (!gcd_test(r)) {
|
||||
unsat_row = r;
|
||||
TRACE("arith_eq_solver", print_row(tout << "unsat: ", unsat_row); );
|
||||
return false;
|
||||
}
|
||||
unsigned index = find_abs_min(r);
|
||||
SASSERT(1 <= index && index < r.size());
|
||||
numeral a = r[index];
|
||||
numeral abs_a = abs(a);
|
||||
if (abs_a.is_zero()) {
|
||||
continue;
|
||||
}
|
||||
else if (abs_a.is_one()) {
|
||||
for (unsigned j = i+1; j < todo.size(); ++j) {
|
||||
substitute(rows[todo[j]], r, index);
|
||||
}
|
||||
for (unsigned j = 0; j < done.size(); ++j) {
|
||||
row& r2 = rows[done[j]];
|
||||
if (!r2[index].is_zero()) {
|
||||
substitute(r2, r, index);
|
||||
todo.push_back(done[j]);
|
||||
done.erase(done.begin()+j);
|
||||
--j;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
done.push_back(todo[i]);
|
||||
}
|
||||
}
|
||||
|
||||
TRACE("arith_eq_solver",
|
||||
tout << ((done.size()<=1)?"solved ":"incomplete check ") << done.size() << "\n";
|
||||
for (unsigned i = 0; i < done.size(); ++i) {
|
||||
print_row(tout, rows[done[i]]);
|
||||
}
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Partial solver based on the omega test equalities.
|
||||
// unsatisfiability is not preserved when eliminating
|
||||
// auxiliary variables.
|
||||
//
|
||||
|
||||
bool arith_eq_solver::solve_integer_equations_omega(
|
||||
vector<row> & rows,
|
||||
row& unsat_row
|
||||
)
|
||||
{
|
||||
unsigned index;
|
||||
bool is_fresh;
|
||||
vector<row> rows_solved;
|
||||
unsigned_vector indices;
|
||||
unsigned_vector aux_indices;
|
||||
|
||||
|
||||
for (unsigned i = 0; i < rows.size(); ++i) {
|
||||
rows_solved.push_back(rows[i]);
|
||||
row& r = rows_solved.back();
|
||||
for (unsigned j = 0; j + 1 < rows_solved.size(); ++j) {
|
||||
substitute(r, rows_solved[j], indices[j]);
|
||||
}
|
||||
if (!solve_integer_equation(r, index, is_fresh)) {
|
||||
unsat_row = r;
|
||||
gcd_normalize(unsat_row);
|
||||
// invert the substitution for every index that is fresh.
|
||||
|
||||
TRACE("arith_eq_solver",
|
||||
tout << "unsat:\n";
|
||||
print_row(tout, unsat_row);
|
||||
for (unsigned l = 0; l + 1< rows_solved.size(); ++l) {
|
||||
print_row(tout, rows_solved[l]);
|
||||
});
|
||||
|
||||
for (unsigned j = rows_solved.size()-1; j > 0; ) {
|
||||
--j;
|
||||
row& solved_row = rows_solved[j];
|
||||
unsigned index_j = indices[j];
|
||||
unsigned aux_index_j = aux_indices[j];
|
||||
SASSERT(index_j <= aux_index_j);
|
||||
if (unsat_row.size() <= aux_index_j) {
|
||||
unsat_row.resize(aux_index_j+1);
|
||||
}
|
||||
numeral m = solved_row[aux_index_j];
|
||||
numeral k = unsat_row[aux_index_j];
|
||||
if (aux_index_j != index_j && !k.is_zero()) {
|
||||
//
|
||||
// solved_row: -x_index + m*sigma + r1 = 0
|
||||
// unsat_row: k*sigma + r2 = 0
|
||||
//
|
||||
// <=>
|
||||
//
|
||||
// solved_row: -k*x_index + k*m*sigma + k*r1 = 0
|
||||
// unsat_row: m*k*sigma + m*r2 = 0
|
||||
//
|
||||
// =>
|
||||
//
|
||||
// m*k*sigma + m*r2 + k*x_index - k*m*sigma - k*r1 = 0
|
||||
//
|
||||
for (unsigned l = 0; l < unsat_row.size(); ++l) {
|
||||
unsat_row[l] *= m;
|
||||
unsat_row[l] -= k*solved_row[l];
|
||||
}
|
||||
for (unsigned l = unsat_row.size(); l < solved_row.size(); ++l) {
|
||||
unsat_row.push_back(solved_row[l]);
|
||||
}
|
||||
|
||||
gcd_normalize(unsat_row);
|
||||
TRACE("arith_eq_solver",
|
||||
tout << "gcd: ";
|
||||
print_row(tout, solved_row);
|
||||
print_row(tout, unsat_row);
|
||||
);
|
||||
|
||||
}
|
||||
if (gcd_test(unsat_row)) {
|
||||
TRACE("arith_eq_solver", tout << "missed pure explanation\n";);
|
||||
return true;
|
||||
}
|
||||
SASSERT(!gcd_test(unsat_row));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else if (r[index].is_zero()) {
|
||||
// Row is trival
|
||||
rows_solved.pop_back();
|
||||
continue;
|
||||
}
|
||||
else if (!abs(r[index]).is_one()) {
|
||||
//
|
||||
// The solution introduces a fresh auxiliary variable.
|
||||
// Make space for this variable as a fresh numeral.
|
||||
//
|
||||
indices.push_back(index);
|
||||
aux_indices.push_back(r.size());
|
||||
|
||||
r.push_back(r[index]);
|
||||
r[index] = numeral(-1);
|
||||
|
||||
// re-solve the same row.
|
||||
--i;
|
||||
}
|
||||
else {
|
||||
indices.push_back(index);
|
||||
aux_indices.push_back(index);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Eliminate variables by searching for combination of rows where
|
||||
// the coefficients have gcd = 1.
|
||||
//
|
||||
|
||||
bool arith_eq_solver::solve_integer_equations_gcd(
|
||||
vector<row> & rows,
|
||||
row& unsat_row
|
||||
)
|
||||
{
|
||||
unsigned_vector live, useful, gcd_pos;
|
||||
vector<rational> gcds;
|
||||
rational u, v;
|
||||
|
||||
if (rows.empty()) {
|
||||
return true;
|
||||
}
|
||||
for (unsigned i = 0; i < rows.size(); ++i) {
|
||||
live.push_back(i);
|
||||
row& r = rows[i];
|
||||
gcd_normalize(r);
|
||||
if (!gcd_test(r)) {
|
||||
unsat_row = r;
|
||||
TRACE("arith_eq_solver", print_row(tout << "input is unsat: ", unsat_row); );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
unsigned max_column = rows[0].size();
|
||||
bool change = true;
|
||||
while (change && !live.empty()) {
|
||||
change = false;
|
||||
for (unsigned i = 1; i < max_column; ++i) {
|
||||
rational g(0);
|
||||
gcds.reset();
|
||||
gcd_pos.reset();
|
||||
unsigned j = 0;
|
||||
for (; j < live.size(); ++j) {
|
||||
rational const& k = rows[live[j]][i];
|
||||
if (k.is_zero()) {
|
||||
continue;
|
||||
}
|
||||
if (g.is_zero()) {
|
||||
g = abs(k);
|
||||
}
|
||||
else {
|
||||
g = gcd(g, abs(k));
|
||||
}
|
||||
if (abs(g).is_one()) {
|
||||
break;
|
||||
}
|
||||
gcds.push_back(g);
|
||||
gcd_pos.push_back(live[j]);
|
||||
}
|
||||
if (j == live.size()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
change = true;
|
||||
// found gcd, now identify reduced set of rows with GCD = 1.
|
||||
g = abs(rows[live[j]][i]);
|
||||
useful.push_back(live[j]);
|
||||
unsigned live_pos = j;
|
||||
for (j = gcds.size(); !g.is_one() && j > 0; ) {
|
||||
SASSERT(g.is_pos());
|
||||
--j;
|
||||
if (j == 0 || !gcd(g, gcds[j-1]).is_one()) {
|
||||
useful.push_back(gcd_pos[j]);
|
||||
g = gcd(g, gcds[j]);
|
||||
SASSERT(j == 0 || gcd(g,gcds[j-1]).is_one());
|
||||
}
|
||||
}
|
||||
//
|
||||
// we now have a set "useful" of rows whose combined GCD = 1.
|
||||
// pivot the remaining with the first row.
|
||||
//
|
||||
row& r0 = rows[useful[0]];
|
||||
for (j = 1; j < useful.size(); ++j) {
|
||||
row& r1 = rows[useful[j]];
|
||||
g = gcd(r0[i], r1[i], u, v);
|
||||
for (unsigned k = 0; k < max_column; ++k) {
|
||||
r0[k] = u*r0[k] + v*r1[k];
|
||||
}
|
||||
SASSERT(g == r0[i]);
|
||||
}
|
||||
SASSERT(abs(r0[i]).is_one());
|
||||
live.erase(live.begin()+live_pos);
|
||||
for (j = 0; j < live.size(); ++j) {
|
||||
row& r = rows[live[j]];
|
||||
if (!r[i].is_zero()) {
|
||||
substitute(r, r0, i);
|
||||
gcd_normalize(r);
|
||||
if (!gcd_test(r)) {
|
||||
unsat_row = r;
|
||||
TRACE("arith_eq_solver", print_row(tout << "unsat: ", unsat_row); );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TRACE("arith_eq_solver",
|
||||
tout << ((live.size()<=1)?"solved ":"incomplete check ") << live.size() << "\n";
|
||||
for (unsigned i = 0; i < live.size(); ++i) {
|
||||
print_row(tout, rows[live[i]]);
|
||||
}
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
108
lib/arith_eq_solver.h
Normal file
108
lib/arith_eq_solver.h
Normal file
|
@ -0,0 +1,108 @@
|
|||
/*++
|
||||
Copyright (c) 2007 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
arith_eq_solver.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Solver for linear arithmetic equalities.
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2012-02-25
|
||||
|
||||
--*/
|
||||
#ifndef _ARITH_EQ_SOLVER_H_
|
||||
#define _ARITH_EQ_SOLVER_H_
|
||||
|
||||
#include"arith_decl_plugin.h"
|
||||
#include"arith_rewriter.h"
|
||||
|
||||
/**
|
||||
\brief Simplifier for the arith family.
|
||||
*/
|
||||
class arith_eq_solver {
|
||||
typedef rational numeral;
|
||||
|
||||
ast_manager& m;
|
||||
params_ref m_params;
|
||||
arith_util m_util;
|
||||
arith_rewriter m_arith_rewriter;
|
||||
|
||||
bool is_neg_poly(expr * t) const;
|
||||
|
||||
void prop_mod_const(expr * e, unsigned depth, numeral const& k, expr_ref& result);
|
||||
|
||||
bool gcd_test(vector<numeral>& value);
|
||||
unsigned find_abs_min(vector<numeral>& values);
|
||||
void gcd_normalize(vector<numeral>& values);
|
||||
void substitute(vector<numeral>& r, vector<numeral> const& s, unsigned index);
|
||||
bool solve_integer_equations_units(
|
||||
vector<vector<numeral> > & rows,
|
||||
vector<numeral>& unsat_row
|
||||
);
|
||||
|
||||
bool solve_integer_equations_omega(
|
||||
vector<vector<numeral> > & rows,
|
||||
vector<numeral>& unsat_row
|
||||
);
|
||||
|
||||
void compute_hnf(vector<vector<numeral> >& A);
|
||||
|
||||
bool solve_integer_equations_hermite(
|
||||
vector<vector<numeral> > & rows,
|
||||
vector<numeral>& unsat_row
|
||||
);
|
||||
|
||||
bool solve_integer_equations_gcd(
|
||||
vector<vector<numeral> > & rows,
|
||||
vector<numeral>& unsat_row
|
||||
);
|
||||
|
||||
public:
|
||||
arith_eq_solver(ast_manager & m, params_ref const& p = params_ref());
|
||||
~arith_eq_solver();
|
||||
|
||||
// Integer linear solver for a single equation.
|
||||
// The array values contains integer coefficients
|
||||
//
|
||||
// Determine integer solutions to:
|
||||
//
|
||||
// a+k = 0
|
||||
//
|
||||
// where a = sum_i a_i*k_i
|
||||
//
|
||||
|
||||
typedef vector<numeral> row;
|
||||
typedef vector<row> matrix;
|
||||
|
||||
bool solve_integer_equation(
|
||||
row& values,
|
||||
unsigned& index,
|
||||
bool& is_fresh
|
||||
);
|
||||
|
||||
// Integer linear solver.
|
||||
// Determine integer solutions to:
|
||||
//
|
||||
// a+k = 0
|
||||
//
|
||||
// where a = sum_i a_i*k_i
|
||||
//
|
||||
// Solution, if there is any, is returned as a substitution.
|
||||
// The return value is "true".
|
||||
// If there is no solution, then return "false".
|
||||
// together with equality "eq_unsat", such that
|
||||
//
|
||||
// eq_unsat = 0
|
||||
//
|
||||
// is implied and is unsatisfiable over the integers.
|
||||
//
|
||||
|
||||
bool solve_integer_equations(vector<row>& rows, row& unsat_row);
|
||||
|
||||
};
|
||||
|
||||
#endif /* _ARITH_EQ_SOLVER_H_ */
|
1493
lib/arith_rewriter.cpp
Normal file
1493
lib/arith_rewriter.cpp
Normal file
File diff suppressed because it is too large
Load diff
183
lib/arith_rewriter.h
Normal file
183
lib/arith_rewriter.h
Normal file
|
@ -0,0 +1,183 @@
|
|||
/*++
|
||||
Copyright (c) 2011 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
arith_rewriter.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Basic rewriting rules for arithmetic
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo (leonardo) 2011-04-10
|
||||
|
||||
Notes:
|
||||
|
||||
--*/
|
||||
#ifndef _ARITH_REWRITER_H_
|
||||
#define _ARITH_REWRITER_H_
|
||||
|
||||
#include"poly_rewriter.h"
|
||||
#include"arith_decl_plugin.h"
|
||||
|
||||
class arith_rewriter_core {
|
||||
protected:
|
||||
typedef rational numeral;
|
||||
arith_util m_util;
|
||||
bool m_expand_power;
|
||||
bool m_mul2power;
|
||||
bool m_expand_tan;
|
||||
|
||||
ast_manager & m() const { return m_util.get_manager(); }
|
||||
family_id get_fid() const { return m_util.get_family_id(); }
|
||||
|
||||
bool is_numeral(expr * n) const { return m_util.is_numeral(n); }
|
||||
bool is_numeral(expr * n, numeral & r) const { return m_util.is_numeral(n, r); }
|
||||
bool is_zero(expr * n) const { return m_util.is_zero(n); }
|
||||
bool is_minus_one(expr * n) const { return m_util.is_minus_one(n); }
|
||||
void normalize(numeral & c, sort * s) {}
|
||||
app * mk_numeral(numeral const & r, sort * s) { return m_util.mk_numeral(r, s); }
|
||||
decl_kind add_decl_kind() const { return OP_ADD; }
|
||||
decl_kind mul_decl_kind() const { return OP_MUL; }
|
||||
bool use_power() const { return m_mul2power && !m_expand_power; }
|
||||
decl_kind power_decl_kind() const { return OP_POWER; }
|
||||
public:
|
||||
arith_rewriter_core(ast_manager & m):m_util(m) {}
|
||||
};
|
||||
|
||||
class arith_rewriter : public poly_rewriter<arith_rewriter_core> {
|
||||
bool m_arith_lhs;
|
||||
bool m_gcd_rounding;
|
||||
bool m_eq2ineq;
|
||||
bool m_elim_to_real;
|
||||
bool m_push_to_real;
|
||||
bool m_anum_simp;
|
||||
bool m_elim_rem;
|
||||
unsigned m_max_degree;
|
||||
|
||||
void get_coeffs_gcd(expr * t, numeral & g, bool & first, unsigned & num_consts);
|
||||
enum const_treatment { CT_FLOOR, CT_CEIL, CT_FALSE };
|
||||
bool div_polynomial(expr * t, numeral const & g, const_treatment ct, expr_ref & result);
|
||||
enum op_kind { LE, GE, EQ };
|
||||
static op_kind inv(op_kind k) { return k == LE ? GE : (k == GE ? LE : EQ); }
|
||||
bool is_bound(expr * arg1, expr * arg2, op_kind kind, expr_ref & result);
|
||||
br_status mk_le_ge_eq_core(expr * arg1, expr * arg2, op_kind kind, expr_ref & result);
|
||||
|
||||
bool elim_to_real_var(expr * var, expr_ref & new_var);
|
||||
bool elim_to_real_mon(expr * monomial, expr_ref & new_monomial);
|
||||
bool elim_to_real_pol(expr * p, expr_ref & new_p);
|
||||
bool elim_to_real(expr * arg1, expr * arg2, expr_ref & new_arg1, expr_ref & new_arg2);
|
||||
|
||||
void updt_local_params(params_ref const & p);
|
||||
|
||||
bool is_anum_simp_target(unsigned num_args, expr * const * args);
|
||||
|
||||
br_status mk_div_irrat_rat(expr * arg1, expr * arg2, expr_ref & result);
|
||||
br_status mk_div_rat_irrat(expr * arg1, expr * arg2, expr_ref & result);
|
||||
br_status mk_div_irrat_irrat(expr * arg1, expr * arg2, expr_ref & result);
|
||||
|
||||
bool is_reduce_power_target(expr * arg, bool is_eq);
|
||||
expr * reduce_power(expr * arg, bool is_eq);
|
||||
br_status reduce_power(expr * arg1, expr * arg2, op_kind kind, expr_ref & result);
|
||||
|
||||
bool is_pi_multiple(expr * t, rational & k);
|
||||
bool is_pi_offset(expr * t, rational & k, expr * & m);
|
||||
bool is_2_pi_integer(expr * t);
|
||||
bool is_2_pi_integer_offset(expr * t, expr * & m);
|
||||
bool is_pi_integer(expr * t);
|
||||
bool is_pi_integer_offset(expr * t, expr * & m);
|
||||
expr * mk_sin_value(rational const & k);
|
||||
app * mk_sqrt(rational const & k);
|
||||
|
||||
public:
|
||||
arith_rewriter(ast_manager & m, params_ref const & p = params_ref()):
|
||||
poly_rewriter<arith_rewriter_core>(m, p) {
|
||||
updt_local_params(p);
|
||||
}
|
||||
|
||||
void updt_params(params_ref const & p);
|
||||
|
||||
static void get_param_descrs(param_descrs & r);
|
||||
|
||||
br_status mk_app_core(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result);
|
||||
void mk_app(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result) {
|
||||
if (mk_app_core(f, num_args, args, result) == BR_FAILED)
|
||||
result = m().mk_app(f, num_args, args);
|
||||
}
|
||||
|
||||
br_status mk_eq_core(expr * arg1, expr * arg2, expr_ref & result);
|
||||
br_status mk_le_core(expr * arg1, expr * arg2, expr_ref & result);
|
||||
br_status mk_lt_core(expr * arg1, expr * arg2, expr_ref & result);
|
||||
br_status mk_ge_core(expr * arg1, expr * arg2, expr_ref & result);
|
||||
br_status mk_gt_core(expr * arg1, expr * arg2, expr_ref & result);
|
||||
|
||||
br_status mk_add_core(unsigned num_args, expr * const * args, expr_ref & result);
|
||||
br_status mk_mul_core(unsigned num_args, expr * const * args, expr_ref & result);
|
||||
|
||||
void mk_eq(expr * arg1, expr * arg2, expr_ref & result) {
|
||||
if (mk_eq_core(arg1, arg2, result) == BR_FAILED)
|
||||
result = m_util.mk_le(arg1, arg2);
|
||||
}
|
||||
void mk_le(expr * arg1, expr * arg2, expr_ref & result) {
|
||||
if (mk_le_core(arg1, arg2, result) == BR_FAILED)
|
||||
result = m_util.mk_le(arg1, arg2);
|
||||
}
|
||||
void mk_lt(expr * arg1, expr * arg2, expr_ref & result) { mk_lt_core(arg1, arg2, result); }
|
||||
void mk_ge(expr * arg1, expr * arg2, expr_ref & result) {
|
||||
if (mk_ge_core(arg1, arg2, result) == BR_FAILED)
|
||||
result = m_util.mk_ge(arg1, arg2);
|
||||
}
|
||||
void mk_gt(expr * arg1, expr * arg2, expr_ref & result) { mk_gt_core(arg1, arg2, result); }
|
||||
|
||||
br_status mk_div_core(expr * arg1, expr * arg2, expr_ref & result);
|
||||
br_status mk_idiv_core(expr * arg1, expr * arg2, expr_ref & result);
|
||||
br_status mk_mod_core(expr * arg1, expr * arg2, expr_ref & result);
|
||||
br_status mk_rem_core(expr * arg1, expr * arg2, expr_ref & result);
|
||||
br_status mk_power_core(expr* arg1, expr* arg2, expr_ref & result);
|
||||
void mk_div(expr * arg1, expr * arg2, expr_ref & result) {
|
||||
if (mk_div_core(arg1, arg2, result) == BR_FAILED)
|
||||
result = m().mk_app(get_fid(), OP_DIV, arg1, arg2);
|
||||
}
|
||||
void mk_idiv(expr * arg1, expr * arg2, expr_ref & result) {
|
||||
if (mk_idiv_core(arg1, arg2, result) == BR_FAILED)
|
||||
result = m().mk_app(get_fid(), OP_IDIV, arg1, arg2);
|
||||
}
|
||||
void mk_mod(expr * arg1, expr * arg2, expr_ref & result) {
|
||||
if (mk_mod_core(arg1, arg2, result) == BR_FAILED)
|
||||
result = m().mk_app(get_fid(), OP_MOD, arg1, arg2);
|
||||
}
|
||||
void mk_rem(expr * arg1, expr * arg2, expr_ref & result) {
|
||||
if (mk_rem_core(arg1, arg2, result) == BR_FAILED)
|
||||
result = m().mk_app(get_fid(), OP_REM, arg1, arg2);
|
||||
}
|
||||
|
||||
br_status mk_to_int_core(expr * arg, expr_ref & result);
|
||||
br_status mk_to_real_core(expr * arg, expr_ref & result);
|
||||
void mk_to_int(expr * arg, expr_ref & result) {
|
||||
if (mk_to_int_core(arg, result) == BR_FAILED)
|
||||
result = m().mk_app(get_fid(), OP_TO_INT, 1, &arg);
|
||||
}
|
||||
void mk_to_real(expr * arg, expr_ref & result) {
|
||||
if (mk_to_real_core(arg, result) == BR_FAILED)
|
||||
result = m().mk_app(get_fid(), OP_TO_REAL, 1, &arg);
|
||||
}
|
||||
br_status mk_is_int(expr * arg, expr_ref & result);
|
||||
|
||||
void set_cancel(bool f);
|
||||
|
||||
br_status mk_sin_core(expr * arg, expr_ref & result);
|
||||
br_status mk_cos_core(expr * arg, expr_ref & result);
|
||||
br_status mk_tan_core(expr * arg, expr_ref & result);
|
||||
|
||||
br_status mk_asin_core(expr * arg, expr_ref & result);
|
||||
br_status mk_acos_core(expr * arg, expr_ref & result);
|
||||
br_status mk_atan_core(expr * arg, expr_ref & result);
|
||||
|
||||
br_status mk_sinh_core(expr * arg, expr_ref & result);
|
||||
br_status mk_cosh_core(expr * arg, expr_ref & result);
|
||||
br_status mk_tanh_core(expr * arg, expr_ref & result);
|
||||
};
|
||||
|
||||
#endif
|
26
lib/arith_simplifier_params.cpp
Normal file
26
lib/arith_simplifier_params.cpp
Normal file
|
@ -0,0 +1,26 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
arith_simplifier_params.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
<abstract>
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-05-09.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#include"arith_simplifier_params.h"
|
||||
|
||||
void arith_simplifier_params::register_params(ini_params & p) {
|
||||
p.register_bool_param("ARITH_EXPAND_EQS", m_arith_expand_eqs);
|
||||
p.register_bool_param("ARITH_PROCESS_ALL_EQS", m_arith_process_all_eqs);
|
||||
}
|
||||
|
37
lib/arith_simplifier_params.h
Normal file
37
lib/arith_simplifier_params.h
Normal file
|
@ -0,0 +1,37 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
arith_simplifier_params.h
|
||||
|
||||
Abstract:
|
||||
|
||||
<abstract>
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-05-09.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _ARITH_SIMPLIFIER_PARAMS_H_
|
||||
#define _ARITH_SIMPLIFIER_PARAMS_H_
|
||||
|
||||
#include"ini_file.h"
|
||||
|
||||
struct arith_simplifier_params {
|
||||
bool m_arith_expand_eqs;
|
||||
bool m_arith_process_all_eqs;
|
||||
|
||||
arith_simplifier_params():
|
||||
m_arith_expand_eqs(false),
|
||||
m_arith_process_all_eqs(false) {
|
||||
}
|
||||
|
||||
void register_params(ini_params & p);
|
||||
};
|
||||
|
||||
#endif /* _ARITH_SIMPLIFIER_PARAMS_H_ */
|
||||
|
442
lib/arith_simplifier_plugin.cpp
Normal file
442
lib/arith_simplifier_plugin.cpp
Normal file
|
@ -0,0 +1,442 @@
|
|||
/*++
|
||||
Copyright (c) 2007 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
arith_simplifier_plugin.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Simplifier for the arithmetic family.
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo (leonardo) 2008-01-08
|
||||
|
||||
--*/
|
||||
#include"arith_simplifier_plugin.h"
|
||||
#include"ast_pp.h"
|
||||
#include"ast_ll_pp.h"
|
||||
#include"ast_smt2_pp.h"
|
||||
|
||||
arith_simplifier_plugin::~arith_simplifier_plugin() {
|
||||
}
|
||||
|
||||
arith_simplifier_plugin::arith_simplifier_plugin(ast_manager & m, basic_simplifier_plugin & b, arith_simplifier_params & p):
|
||||
poly_simplifier_plugin(symbol("arith"), m, OP_ADD, OP_MUL, OP_UMINUS, OP_SUB, OP_NUM),
|
||||
m_params(p),
|
||||
m_util(m),
|
||||
m_bsimp(b),
|
||||
m_int_zero(m),
|
||||
m_real_zero(m) {
|
||||
m_int_zero = m_util.mk_numeral(rational(0), true);
|
||||
m_real_zero = m_util.mk_numeral(rational(0), false);
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Return true if the first monomial of t is negative.
|
||||
*/
|
||||
bool arith_simplifier_plugin::is_neg_poly(expr * t) const {
|
||||
if (m_util.is_add(t)) {
|
||||
t = to_app(t)->get_arg(0);
|
||||
}
|
||||
if (m_util.is_mul(t)) {
|
||||
t = to_app(t)->get_arg(0);
|
||||
rational r;
|
||||
bool is_int;
|
||||
if (m_util.is_numeral(t, r, is_int))
|
||||
return r.is_neg();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void arith_simplifier_plugin::get_monomial_gcd(expr_ref_vector& monomials, numeral& g) {
|
||||
g = numeral::zero();
|
||||
numeral n;
|
||||
for (unsigned i = 0; !g.is_one() && i < monomials.size(); ++i) {
|
||||
expr* e = monomials[i].get();
|
||||
if (is_numeral(e, n)) {
|
||||
g = gcd(abs(n), g);
|
||||
}
|
||||
else if (is_mul(e) && is_numeral(to_app(e)->get_arg(0), n)) {
|
||||
g = gcd(abs(n), g);
|
||||
}
|
||||
else {
|
||||
g = numeral::one();
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (g.is_zero()) {
|
||||
g = numeral::one();
|
||||
}
|
||||
}
|
||||
|
||||
void arith_simplifier_plugin::div_monomial(expr_ref_vector& monomials, numeral const& g) {
|
||||
numeral n;
|
||||
for (unsigned i = 0; i < monomials.size(); ++i) {
|
||||
expr* e = monomials[i].get();
|
||||
if (is_numeral(e, n)) {
|
||||
SASSERT((n/g).is_int());
|
||||
monomials[i] = mk_numeral(n/g);
|
||||
}
|
||||
else if (is_mul(e) && is_numeral(to_app(e)->get_arg(0), n)) {
|
||||
SASSERT((n/g).is_int());
|
||||
monomials[i] = mk_mul(n/g, to_app(e)->get_arg(1));
|
||||
}
|
||||
else {
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void arith_simplifier_plugin::gcd_reduce_monomial(expr_ref_vector& monomials, numeral& k) {
|
||||
numeral g, n;
|
||||
|
||||
get_monomial_gcd(monomials, g);
|
||||
g = gcd(abs(k), g);
|
||||
|
||||
if (g.is_one()) {
|
||||
return;
|
||||
}
|
||||
SASSERT(g.is_pos());
|
||||
|
||||
k = k / g;
|
||||
div_monomial(monomials, g);
|
||||
|
||||
}
|
||||
|
||||
template<arith_simplifier_plugin::op_kind Kind>
|
||||
void arith_simplifier_plugin::mk_le_ge_eq_core(expr * arg1, expr * arg2, expr_ref & result) {
|
||||
set_curr_sort(arg1);
|
||||
bool is_int = m_curr_sort->get_decl_kind() == INT_SORT;
|
||||
expr_ref_vector monomials(m_manager);
|
||||
rational k;
|
||||
TRACE("arith_eq_bug", tout << mk_ismt2_pp(arg1, m_manager) << "\n" << mk_ismt2_pp(arg2, m_manager) << "\n";);
|
||||
process_sum_of_monomials(false, arg1, monomials, k);
|
||||
process_sum_of_monomials(true, arg2, monomials, k);
|
||||
k.neg();
|
||||
if (is_int) {
|
||||
numeral g;
|
||||
get_monomial_gcd(monomials, g);
|
||||
if (!g.is_one()) {
|
||||
div_monomial(monomials, g);
|
||||
switch(Kind) {
|
||||
case LE:
|
||||
//
|
||||
// g*monmials' <= k
|
||||
// <=>
|
||||
// monomials' <= floor(k/g)
|
||||
//
|
||||
k = floor(k/g);
|
||||
break;
|
||||
case GE:
|
||||
//
|
||||
// g*monmials' >= k
|
||||
// <=>
|
||||
// monomials' >= ceil(k/g)
|
||||
//
|
||||
k = ceil(k/g);
|
||||
break;
|
||||
case EQ:
|
||||
k = k/g;
|
||||
if (!k.is_int()) {
|
||||
result = m_manager.mk_false();
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
expr_ref lhs(m_manager);
|
||||
mk_sum_of_monomials(monomials, lhs);
|
||||
if (m_util.is_numeral(lhs)) {
|
||||
SASSERT(lhs == mk_zero());
|
||||
if (( Kind == LE && numeral::zero() <= k) ||
|
||||
( Kind == GE && numeral::zero() >= k) ||
|
||||
( Kind == EQ && numeral::zero() == k))
|
||||
result = m_manager.mk_true();
|
||||
else
|
||||
result = m_manager.mk_false();
|
||||
}
|
||||
else {
|
||||
|
||||
if (is_neg_poly(lhs)) {
|
||||
expr_ref neg_lhs(m_manager);
|
||||
mk_uminus(lhs, neg_lhs);
|
||||
lhs = neg_lhs;
|
||||
k.neg();
|
||||
expr * rhs = m_util.mk_numeral(k, is_int);
|
||||
switch (Kind) {
|
||||
case LE:
|
||||
result = m_util.mk_ge(lhs, rhs);
|
||||
break;
|
||||
case GE:
|
||||
result = m_util.mk_le(lhs, rhs);
|
||||
break;
|
||||
case EQ:
|
||||
result = m_manager.mk_eq(lhs, rhs);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
expr * rhs = m_util.mk_numeral(k, is_int);
|
||||
switch (Kind) {
|
||||
case LE:
|
||||
result = m_util.mk_le(lhs, rhs);
|
||||
break;
|
||||
case GE:
|
||||
result = m_util.mk_ge(lhs, rhs);
|
||||
break;
|
||||
case EQ:
|
||||
result = m_manager.mk_eq(lhs, rhs);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void arith_simplifier_plugin::mk_arith_eq(expr * arg1, expr * arg2, expr_ref & result) {
|
||||
mk_le_ge_eq_core<EQ>(arg1, arg2, result);
|
||||
}
|
||||
|
||||
void arith_simplifier_plugin::mk_le(expr * arg1, expr * arg2, expr_ref & result) {
|
||||
mk_le_ge_eq_core<LE>(arg1, arg2, result);
|
||||
}
|
||||
|
||||
void arith_simplifier_plugin::mk_ge(expr * arg1, expr * arg2, expr_ref & result) {
|
||||
mk_le_ge_eq_core<GE>(arg1, arg2, result);
|
||||
}
|
||||
|
||||
void arith_simplifier_plugin::mk_lt(expr * arg1, expr * arg2, expr_ref & result) {
|
||||
expr_ref tmp(m_manager);
|
||||
mk_le(arg2, arg1, tmp);
|
||||
m_bsimp.mk_not(tmp, result);
|
||||
}
|
||||
|
||||
void arith_simplifier_plugin::mk_gt(expr * arg1, expr * arg2, expr_ref & result) {
|
||||
expr_ref tmp(m_manager);
|
||||
mk_le(arg1, arg2, tmp);
|
||||
m_bsimp.mk_not(tmp, result);
|
||||
}
|
||||
|
||||
void arith_simplifier_plugin::gcd_normalize(numeral & coeff, expr_ref& term) {
|
||||
if (!abs(coeff).is_one()) {
|
||||
set_curr_sort(term);
|
||||
SASSERT(m_curr_sort->get_decl_kind() == INT_SORT);
|
||||
expr_ref_vector monomials(m_manager);
|
||||
rational k;
|
||||
monomials.push_back(mk_numeral(numeral(coeff), true));
|
||||
process_sum_of_monomials(false, term, monomials, k);
|
||||
gcd_reduce_monomial(monomials, k);
|
||||
numeral coeff1;
|
||||
if (!is_numeral(monomials[0].get(), coeff1)) {
|
||||
UNREACHABLE();
|
||||
}
|
||||
if (coeff1 == coeff) {
|
||||
return;
|
||||
}
|
||||
monomials[0] = mk_numeral(k, true);
|
||||
coeff = coeff1;
|
||||
mk_sum_of_monomials(monomials, term);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void arith_simplifier_plugin::mk_div(expr * arg1, expr * arg2, expr_ref & result) {
|
||||
set_curr_sort(arg1);
|
||||
numeral v1, v2;
|
||||
bool is_int;
|
||||
if (m_util.is_numeral(arg2, v2, is_int) && !v2.is_zero()) {
|
||||
SASSERT(!is_int);
|
||||
if (m_util.is_numeral(arg1, v1, is_int))
|
||||
result = m_util.mk_numeral(v1/v2, false);
|
||||
else {
|
||||
numeral k(1);
|
||||
k /= v2;
|
||||
|
||||
expr_ref inv_arg2(m_util.mk_numeral(k, false), m_manager);
|
||||
mk_mul(inv_arg2, arg1, result);
|
||||
}
|
||||
}
|
||||
else
|
||||
result = m_util.mk_div(arg1, arg2);
|
||||
}
|
||||
|
||||
void arith_simplifier_plugin::mk_idiv(expr * arg1, expr * arg2, expr_ref & result) {
|
||||
set_curr_sort(arg1);
|
||||
numeral v1, v2;
|
||||
bool is_int;
|
||||
if (m_util.is_numeral(arg1, v1, is_int) && m_util.is_numeral(arg2, v2, is_int) && !v2.is_zero())
|
||||
result = m_util.mk_numeral(div(v1, v2), is_int);
|
||||
else
|
||||
result = m_util.mk_idiv(arg1, arg2);
|
||||
}
|
||||
|
||||
void arith_simplifier_plugin::prop_mod_const(expr * e, unsigned depth, numeral const& k, expr_ref& result) {
|
||||
SASSERT(m_util.is_int(e));
|
||||
SASSERT(k.is_int() && k.is_pos());
|
||||
numeral n;
|
||||
bool is_int;
|
||||
|
||||
if (depth == 0) {
|
||||
result = e;
|
||||
}
|
||||
else if (is_add(e) || is_mul(e)) {
|
||||
expr_ref_vector args(m_manager);
|
||||
expr_ref tmp(m_manager);
|
||||
app* a = to_app(e);
|
||||
for (unsigned i = 0; i < a->get_num_args(); ++i) {
|
||||
prop_mod_const(a->get_arg(i), depth - 1, k, tmp);
|
||||
args.push_back(tmp);
|
||||
}
|
||||
reduce(a->get_decl(), args.size(), args.c_ptr(), result);
|
||||
}
|
||||
else if (m_util.is_numeral(e, n, is_int) && is_int) {
|
||||
result = mk_numeral(mod(n, k), true);
|
||||
}
|
||||
else {
|
||||
result = e;
|
||||
}
|
||||
}
|
||||
|
||||
void arith_simplifier_plugin::mk_mod(expr * arg1, expr * arg2, expr_ref & result) {
|
||||
set_curr_sort(arg1);
|
||||
numeral v1, v2;
|
||||
bool is_int;
|
||||
if (m_util.is_numeral(arg1, v1, is_int) && m_util.is_numeral(arg2, v2, is_int) && !v2.is_zero()) {
|
||||
result = m_util.mk_numeral(mod(v1, v2), is_int);
|
||||
}
|
||||
else if (m_util.is_numeral(arg2, v2, is_int) && is_int && v2.is_one()) {
|
||||
result = m_util.mk_numeral(numeral(0), true);
|
||||
}
|
||||
else if (m_util.is_numeral(arg2, v2, is_int) && is_int && v2.is_pos()) {
|
||||
expr_ref tmp(m_manager);
|
||||
prop_mod_const(arg1, 5, v2, tmp);
|
||||
result = m_util.mk_mod(tmp, arg2);
|
||||
}
|
||||
else {
|
||||
result = m_util.mk_mod(arg1, arg2);
|
||||
}
|
||||
}
|
||||
|
||||
void arith_simplifier_plugin::mk_rem(expr * arg1, expr * arg2, expr_ref & result) {
|
||||
set_curr_sort(arg1);
|
||||
numeral v1, v2;
|
||||
bool is_int;
|
||||
if (m_util.is_numeral(arg1, v1, is_int) && m_util.is_numeral(arg2, v2, is_int) && !v2.is_zero()) {
|
||||
numeral m = mod(v1, v2);
|
||||
//
|
||||
// rem(v1,v2) = if v2 >= 0 then mod(v1,v2) else -mod(v1,v2)
|
||||
//
|
||||
if (v2.is_neg()) {
|
||||
m.neg();
|
||||
}
|
||||
result = m_util.mk_numeral(m, is_int);
|
||||
}
|
||||
else if (m_util.is_numeral(arg2, v2, is_int) && is_int && v2.is_one()) {
|
||||
result = m_util.mk_numeral(numeral(0), true);
|
||||
}
|
||||
else if (m_util.is_numeral(arg2, v2, is_int) && is_int && !v2.is_zero()) {
|
||||
expr_ref tmp(m_manager);
|
||||
prop_mod_const(arg1, 5, v2, tmp);
|
||||
result = m_util.mk_mod(tmp, arg2);
|
||||
if (v2.is_neg()) {
|
||||
result = m_util.mk_uminus(result);
|
||||
}
|
||||
}
|
||||
else {
|
||||
result = m_util.mk_rem(arg1, arg2);
|
||||
}
|
||||
}
|
||||
|
||||
void arith_simplifier_plugin::mk_to_real(expr * arg, expr_ref & result) {
|
||||
numeral v;
|
||||
if (m_util.is_numeral(arg, v))
|
||||
result = m_util.mk_numeral(v, false);
|
||||
else
|
||||
result = m_util.mk_to_real(arg);
|
||||
}
|
||||
|
||||
void arith_simplifier_plugin::mk_to_int(expr * arg, expr_ref & result) {
|
||||
numeral v;
|
||||
if (m_util.is_numeral(arg, v))
|
||||
result = m_util.mk_numeral(floor(v), true);
|
||||
else if (m_util.is_to_real(arg))
|
||||
result = to_app(arg)->get_arg(0);
|
||||
else
|
||||
result = m_util.mk_to_int(arg);
|
||||
}
|
||||
|
||||
void arith_simplifier_plugin::mk_is_int(expr * arg, expr_ref & result) {
|
||||
numeral v;
|
||||
if (m_util.is_numeral(arg, v))
|
||||
result = v.is_int()?m_manager.mk_true():m_manager.mk_false();
|
||||
else if (m_util.is_to_real(arg))
|
||||
result = m_manager.mk_true();
|
||||
else
|
||||
result = m_util.mk_is_int(arg);
|
||||
}
|
||||
|
||||
bool arith_simplifier_plugin::reduce(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result) {
|
||||
set_reduce_invoked();
|
||||
SASSERT(f->get_family_id() == m_fid);
|
||||
TRACE("arith_simplifier_plugin", tout << mk_pp(f, m_manager) << "\n";
|
||||
for (unsigned i = 0; i < num_args; i++) tout << mk_pp(args[i], m_manager) << "\n";);
|
||||
arith_op_kind k = static_cast<arith_op_kind>(f->get_decl_kind());
|
||||
switch (k) {
|
||||
case OP_NUM: return false;
|
||||
case OP_LE: if (m_presimp) return false; SASSERT(num_args == 2); mk_le(args[0], args[1], result); break;
|
||||
case OP_GE: if (m_presimp) return false; SASSERT(num_args == 2); mk_ge(args[0], args[1], result); break;
|
||||
case OP_LT: if (m_presimp) return false; SASSERT(num_args == 2); mk_lt(args[0], args[1], result); break;
|
||||
case OP_GT: if (m_presimp) return false; SASSERT(num_args == 2); mk_gt(args[0], args[1], result); break;
|
||||
case OP_ADD: mk_add(num_args, args, result); break;
|
||||
case OP_SUB: mk_sub(num_args, args, result); break;
|
||||
case OP_UMINUS: SASSERT(num_args == 1); mk_uminus(args[0], result); break;
|
||||
case OP_MUL:
|
||||
mk_mul(num_args, args, result);
|
||||
TRACE("arith_simplifier_plugin", tout << mk_pp(result, m_manager) << "\n";);
|
||||
break;
|
||||
case OP_DIV: SASSERT(num_args == 2); mk_div(args[0], args[1], result); break;
|
||||
case OP_IDIV: SASSERT(num_args == 2); mk_idiv(args[0], args[1], result); break;
|
||||
case OP_REM: SASSERT(num_args == 2); mk_rem(args[0], args[1], result); break;
|
||||
case OP_MOD: SASSERT(num_args == 2); mk_mod(args[0], args[1], result); break;
|
||||
case OP_TO_REAL: SASSERT(num_args == 1); mk_to_real(args[0], result); break;
|
||||
case OP_TO_INT: SASSERT(num_args == 1); mk_to_int(args[0], result); break;
|
||||
case OP_IS_INT: SASSERT(num_args == 1); mk_is_int(args[0], result); break;
|
||||
case OP_POWER: return false;
|
||||
case OP_IRRATIONAL_ALGEBRAIC_NUM: return false;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return false;
|
||||
}
|
||||
TRACE("arith_simplifier_plugin", tout << mk_pp(result.get(), m_manager) << "\n";);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool arith_simplifier_plugin::is_arith_term(expr * n) const {
|
||||
return n->get_kind() == AST_APP && to_app(n)->get_family_id() == m_fid;
|
||||
}
|
||||
|
||||
bool arith_simplifier_plugin::reduce_eq(expr * lhs, expr * rhs, expr_ref & result) {
|
||||
TRACE("reduce_eq_bug", tout << mk_ismt2_pp(lhs, m_manager) << "\n" << mk_ismt2_pp(rhs, m_manager) << "\n";);
|
||||
set_reduce_invoked();
|
||||
if (m_presimp) {
|
||||
return false;
|
||||
}
|
||||
if (m_params.m_arith_expand_eqs) {
|
||||
expr_ref le(m_manager), ge(m_manager);
|
||||
mk_le_ge_eq_core<LE>(lhs, rhs, le);
|
||||
mk_le_ge_eq_core<GE>(lhs, rhs, ge);
|
||||
m_bsimp.mk_and(le, ge, result);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (m_params.m_arith_process_all_eqs || is_arith_term(lhs) || is_arith_term(rhs)) {
|
||||
mk_arith_eq(lhs, rhs, result);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
95
lib/arith_simplifier_plugin.h
Normal file
95
lib/arith_simplifier_plugin.h
Normal file
|
@ -0,0 +1,95 @@
|
|||
/*++
|
||||
Copyright (c) 2007 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
arith_simplifier_plugin.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Simplifier for the arithmetic family.
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo (leonardo) 2008-01-08
|
||||
|
||||
--*/
|
||||
#ifndef _ARITH_SIMPLIFIER_PLUGIN_H_
|
||||
#define _ARITH_SIMPLIFIER_PLUGIN_H_
|
||||
|
||||
#include"basic_simplifier_plugin.h"
|
||||
#include"poly_simplifier_plugin.h"
|
||||
#include"arith_decl_plugin.h"
|
||||
#include"arith_simplifier_params.h"
|
||||
|
||||
/**
|
||||
\brief Simplifier for the arith family.
|
||||
*/
|
||||
class arith_simplifier_plugin : public poly_simplifier_plugin {
|
||||
public:
|
||||
enum op_kind {
|
||||
LE, GE, EQ
|
||||
};
|
||||
protected:
|
||||
arith_simplifier_params & m_params;
|
||||
arith_util m_util;
|
||||
basic_simplifier_plugin & m_bsimp;
|
||||
expr_ref m_int_zero;
|
||||
expr_ref m_real_zero;
|
||||
|
||||
bool is_neg_poly(expr * t) const;
|
||||
|
||||
template<op_kind k>
|
||||
void mk_le_ge_eq_core(expr * arg1, expr * arg2, expr_ref & result);
|
||||
|
||||
void prop_mod_const(expr * e, unsigned depth, numeral const& k, expr_ref& result);
|
||||
|
||||
void gcd_reduce_monomial(expr_ref_vector& monomials, numeral& k);
|
||||
|
||||
void div_monomial(expr_ref_vector& monomials, numeral const& g);
|
||||
void get_monomial_gcd(expr_ref_vector& monomials, numeral& g);
|
||||
|
||||
public:
|
||||
arith_simplifier_plugin(ast_manager & m, basic_simplifier_plugin & b, arith_simplifier_params & p);
|
||||
~arith_simplifier_plugin();
|
||||
arith_util & get_arith_util() { return m_util; }
|
||||
virtual numeral norm(const numeral & n) { return n; }
|
||||
virtual bool is_numeral(expr * n, rational & val) const { bool f; return m_util.is_numeral(n, val, f); }
|
||||
bool is_numeral(expr * n) const { return m_util.is_numeral(n); }
|
||||
virtual bool is_minus_one(expr * n) const { numeral tmp; return is_numeral(n, tmp) && tmp.is_minus_one(); }
|
||||
virtual expr * get_zero(sort * s) const { return m_util.is_int(s) ? m_int_zero.get() : m_real_zero.get(); }
|
||||
|
||||
virtual app * mk_numeral(numeral const & n) { return m_util.mk_numeral(n, m_curr_sort->get_decl_kind() == INT_SORT); }
|
||||
app * mk_numeral(numeral const & n, bool is_int) { return m_util.mk_numeral(n, is_int); }
|
||||
bool is_int_sort(sort const * s) const { return m_util.is_int(s); }
|
||||
bool is_real_sort(sort const * s) const { return m_util.is_real(s); }
|
||||
bool is_arith_sort(sort const * s) const { return is_int_sort(s) || is_real_sort(s); }
|
||||
bool is_int(expr const * n) const { return m_util.is_int(n); }
|
||||
bool is_le(expr const * n) const { return m_util.is_le(n); }
|
||||
bool is_ge(expr const * n) const { return m_util.is_ge(n); }
|
||||
|
||||
virtual bool is_le_ge(expr * n) const { return is_le(n) || is_ge(n); }
|
||||
|
||||
void mk_le(expr * arg1, expr * arg2, expr_ref & result);
|
||||
void mk_ge(expr * arg1, expr * arg2, expr_ref & result);
|
||||
void mk_lt(expr * arg1, expr * arg2, expr_ref & result);
|
||||
void mk_gt(expr * arg1, expr * arg2, expr_ref & result);
|
||||
void mk_arith_eq(expr * arg1, expr * arg2, expr_ref & result);
|
||||
void mk_div(expr * arg1, expr * arg2, expr_ref & result);
|
||||
void mk_idiv(expr * arg1, expr * arg2, expr_ref & result);
|
||||
void mk_mod(expr * arg1, expr * arg2, expr_ref & result);
|
||||
void mk_rem(expr * arg1, expr * arg2, expr_ref & result);
|
||||
void mk_to_real(expr * arg, expr_ref & result);
|
||||
void mk_to_int(expr * arg, expr_ref & result);
|
||||
void mk_is_int(expr * arg, expr_ref & result);
|
||||
|
||||
virtual bool reduce(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result);
|
||||
virtual bool reduce_eq(expr * lhs, expr * rhs, expr_ref & result);
|
||||
|
||||
bool is_arith_term(expr * n) const;
|
||||
|
||||
void gcd_normalize(numeral & coeff, expr_ref& term);
|
||||
|
||||
};
|
||||
|
||||
#endif /* _ARITH_SIMPLIFIER_PLUGIN_H_ */
|
104
lib/arith_solver_plugin.cpp
Normal file
104
lib/arith_solver_plugin.cpp
Normal file
|
@ -0,0 +1,104 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
arith_solver_plugin.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
<abstract>
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-06-30.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include"arith_solver_plugin.h"
|
||||
#include"ast_pp.h"
|
||||
|
||||
arith_solver_plugin::arith_solver_plugin(arith_simplifier_plugin & simp):
|
||||
solver_plugin(symbol("arith"), simp.get_manager()),
|
||||
m_simplifier(simp) {
|
||||
}
|
||||
|
||||
bool arith_solver_plugin::solve(expr * lhs, expr * rhs, expr_mark const & forbidden, app_ref & var, expr_ref & subst) {
|
||||
rational k;
|
||||
if (!m_simplifier.is_numeral(rhs, k))
|
||||
return false;
|
||||
bool _is_int = m_simplifier.is_int(lhs);
|
||||
ptr_buffer<expr> monomials;
|
||||
ptr_buffer<expr> todo;
|
||||
bool already_found = false;
|
||||
rational c;
|
||||
todo.push_back(lhs);
|
||||
while (!todo.empty()) {
|
||||
expr * curr = todo.back();
|
||||
todo.pop_back();
|
||||
rational coeff;
|
||||
if (m_simplifier.is_add(curr)) {
|
||||
SASSERT(to_app(curr)->get_num_args() == 2);
|
||||
todo.push_back(to_app(curr)->get_arg(1));
|
||||
todo.push_back(to_app(curr)->get_arg(0));
|
||||
}
|
||||
else {
|
||||
if (!already_found) {
|
||||
if (m_simplifier.is_mul(curr) &&
|
||||
m_simplifier.is_numeral(to_app(curr)->get_arg(0), coeff) && !coeff.is_zero() && (!_is_int || coeff.is_minus_one()) &&
|
||||
is_uninterp_const(to_app(curr)->get_arg(1)) &&
|
||||
!forbidden.is_marked(to_app(curr)->get_arg(1))) {
|
||||
c = coeff;
|
||||
var = to_app(to_app(curr)->get_arg(1));
|
||||
already_found = true;
|
||||
}
|
||||
else if (is_uninterp_const(curr) && !forbidden.is_marked(curr)) {
|
||||
c = rational::one();
|
||||
var = to_app(curr);
|
||||
already_found = true;
|
||||
}
|
||||
else {
|
||||
monomials.push_back(curr);
|
||||
}
|
||||
}
|
||||
else {
|
||||
monomials.push_back(curr);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!already_found)
|
||||
return false;
|
||||
SASSERT(!c.is_zero());
|
||||
k /= c;
|
||||
expr_ref_vector new_monomials(m_manager);
|
||||
if (!k.is_zero())
|
||||
new_monomials.push_back(m_simplifier.mk_numeral(k, _is_int));
|
||||
c.neg();
|
||||
expr_ref inv_c(m_manager);
|
||||
if (!c.is_one()) {
|
||||
rational inv(1);
|
||||
inv /= c;
|
||||
inv_c = m_simplifier.mk_numeral(inv, _is_int);
|
||||
}
|
||||
// divide monomials by c
|
||||
unsigned sz = monomials.size();
|
||||
for (unsigned i = 0; i < sz; i++) {
|
||||
expr * m = monomials[i];
|
||||
expr_ref new_m(m_manager);
|
||||
if (!c.is_one())
|
||||
m_simplifier.mk_mul(inv_c, m, new_m);
|
||||
else
|
||||
new_m = m;
|
||||
new_monomials.push_back(new_m);
|
||||
}
|
||||
if (new_monomials.empty())
|
||||
subst = m_simplifier.mk_numeral(rational(0), _is_int);
|
||||
else
|
||||
m_simplifier.mk_add(new_monomials.size(), new_monomials.c_ptr(), subst);
|
||||
TRACE("arith_solver", tout << "solving:\n" << mk_pp(lhs, m_manager) << "\n" << mk_pp(rhs, m_manager)
|
||||
<< "\nresult:\n" << mk_pp(var, m_manager) << "\n" << mk_pp(subst, m_manager) << "\n";);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
34
lib/arith_solver_plugin.h
Normal file
34
lib/arith_solver_plugin.h
Normal file
|
@ -0,0 +1,34 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
arith_solver_plugin.h
|
||||
|
||||
Abstract:
|
||||
|
||||
<abstract>
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-06-30.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _ARITH_SOLVER_PLUGIN_H_
|
||||
#define _ARITH_SOLVER_PLUGIN_H_
|
||||
|
||||
#include"solver_plugin.h"
|
||||
#include"arith_simplifier_plugin.h"
|
||||
|
||||
class arith_solver_plugin : public solver_plugin {
|
||||
arith_simplifier_plugin & m_simplifier;
|
||||
public:
|
||||
arith_solver_plugin(arith_simplifier_plugin & simp);
|
||||
virtual ~arith_solver_plugin() {}
|
||||
virtual bool solve(expr * lhs, expr * rhs, expr_mark const & forbidden, app_ref & var, expr_ref & subst);
|
||||
};
|
||||
|
||||
#endif /* _ARITH_SOLVER_PLUGIN_H_ */
|
||||
|
205
lib/array.h
Normal file
205
lib/array.h
Normal file
|
@ -0,0 +1,205 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
array.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Fixed size arrays
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2011-01-26.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef __ARRAY_H_
|
||||
#define __ARRAY_H_
|
||||
|
||||
template<typename T, bool CallDestructors=true>
|
||||
class array {
|
||||
public:
|
||||
// Return the space needed to store an array of size sz.
|
||||
static size_t space(size_t sz) { return sizeof(T)*sz + sizeof(size_t); }
|
||||
|
||||
private:
|
||||
#define ARRAY_SIZE_IDX -1
|
||||
T * m_data;
|
||||
void destroy_elements() {
|
||||
iterator it = begin();
|
||||
iterator e = end();
|
||||
for (; it != e; ++it) {
|
||||
it->~T();
|
||||
}
|
||||
}
|
||||
|
||||
char * raw_ptr() const { return reinterpret_cast<char*>(reinterpret_cast<size_t*>(m_data) - 1); }
|
||||
|
||||
array & operator=(array const & source);
|
||||
|
||||
void set_data(void * mem, size_t sz) {
|
||||
size_t * _mem = static_cast<size_t*>(mem);
|
||||
*_mem = sz;
|
||||
_mem ++;
|
||||
m_data = reinterpret_cast<T*>(_mem);
|
||||
}
|
||||
|
||||
template<typename Allocator>
|
||||
void allocate(Allocator & a, size_t sz) {
|
||||
size_t * mem = reinterpret_cast<size_t*>(a.allocate(space(sz)));
|
||||
set_data(mem, sz);
|
||||
}
|
||||
|
||||
void init() {
|
||||
iterator it = begin();
|
||||
iterator e = end();
|
||||
for (; it != e; ++it) {
|
||||
new (it) T();
|
||||
}
|
||||
}
|
||||
|
||||
void init(T const * vs) {
|
||||
iterator it = begin();
|
||||
iterator e = end();
|
||||
for (; it != e; ++it, ++vs) {
|
||||
new (it) T(*vs);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
typedef T data;
|
||||
typedef T * iterator;
|
||||
typedef const T * const_iterator;
|
||||
|
||||
array():m_data(0) {}
|
||||
|
||||
/**
|
||||
\brief Store the array in the given chunk of memory (mem).
|
||||
This chunck should be big enough to store space(sz) bytes.
|
||||
*/
|
||||
array(void * mem, size_t sz, T const * vs) {
|
||||
DEBUG_CODE(m_data = 0;);
|
||||
set(mem, sz, vs);
|
||||
}
|
||||
|
||||
// WARNING: the memory allocated will not be automatically freed.
|
||||
array(void * mem, size_t sz, bool init_mem) {
|
||||
DEBUG_CODE(m_data = 0;);
|
||||
set_data(mem, sz);
|
||||
if (init_mem)
|
||||
init();
|
||||
}
|
||||
|
||||
// WARNING: the memory allocated will not be automatically freed.
|
||||
template<typename Allocator>
|
||||
array(Allocator & a, size_t sz, T const * vs) {
|
||||
DEBUG_CODE(m_data = 0;);
|
||||
set(a, sz, vs);
|
||||
}
|
||||
|
||||
// WARNING: the memory allocated will not be automatically freed.
|
||||
template<typename Allocator>
|
||||
array(Allocator & a, size_t sz, bool init_mem) {
|
||||
DEBUG_CODE(m_data = 0;);
|
||||
allocate(a, sz);
|
||||
if (init_mem)
|
||||
init();
|
||||
}
|
||||
|
||||
// WARNING: this does not free the memory used to store the array.
|
||||
// You must free it yourself, or use finalize.
|
||||
~array() {
|
||||
if (m_data && CallDestructors)
|
||||
destroy_elements();
|
||||
}
|
||||
|
||||
// Free the memory used to store the array.
|
||||
template<typename Allocator>
|
||||
void finalize(Allocator & a) {
|
||||
if (m_data) {
|
||||
if (CallDestructors)
|
||||
destroy_elements();
|
||||
a.deallocate(size(), raw_ptr);
|
||||
m_data = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void set(void * mem, size_t sz, T const * vs) {
|
||||
SASSERT(m_data == 0);
|
||||
set_data(mem, sz);
|
||||
init(vs);
|
||||
}
|
||||
|
||||
template<typename Allocator>
|
||||
void set(Allocator & a, size_t sz, T const * vs) {
|
||||
SASSERT(m_data == 0);
|
||||
allocate(a, sz);
|
||||
init(sz, vs);
|
||||
}
|
||||
|
||||
size_t size() const {
|
||||
if (m_data == 0) {
|
||||
return 0;
|
||||
}
|
||||
return reinterpret_cast<size_t *>(m_data)[SIZE_IDX];
|
||||
}
|
||||
|
||||
bool empty() const { return m_data == 0; }
|
||||
|
||||
T & operator[](size_t idx) {
|
||||
SASSERT(idx < size());
|
||||
return m_data[idx];
|
||||
}
|
||||
|
||||
T const & operator[](size_t idx) const {
|
||||
SASSERT(idx < size());
|
||||
return m_data[idx];
|
||||
}
|
||||
|
||||
iterator begin() {
|
||||
return m_data;
|
||||
}
|
||||
|
||||
iterator end() {
|
||||
return m_data + size();
|
||||
}
|
||||
|
||||
const_iterator begin() const {
|
||||
return m_data;
|
||||
}
|
||||
|
||||
const_iterator end() const {
|
||||
return m_data + size();
|
||||
}
|
||||
|
||||
T * c_ptr() { return m_data; }
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class ptr_array : public array<T *, false> {
|
||||
public:
|
||||
ptr_array() {}
|
||||
ptr_array(void * mem, size_t sz, T * const * vs):array<T*, false>(mem, sz, vs) {}
|
||||
template<typename Allocator>
|
||||
ptr_array(Allocator & a, size_t sz, T * const * vs):array<T*, false>(a, sz, vs) {}
|
||||
ptr_array(void * mem, size_t sz, bool init_mem):array<T*, false>(mem, sz, init_mem) {}
|
||||
template<typename Allocator>
|
||||
ptr_array(Allocator & a, size_t sz, bool init_mem):array<T*, false>(a, sz, init_mem) {}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class sarray : public array<T, false> {
|
||||
public:
|
||||
sarray() {}
|
||||
sarray(void * mem, size_t sz, T const * vs):array<T, false>(mem, sz, vs) {}
|
||||
template<typename Allocator>
|
||||
sarray(Allocator & a, size_t sz, T const * vs):array<T, false>(a, sz, vs) {}
|
||||
sarray(void * mem, size_t sz, bool init_mem):array<T, false>(mem, sz, init_mem) {}
|
||||
template<typename Allocator>
|
||||
sarray(Allocator & a, size_t sz, bool init_mem):array<T, false>(a, sz, init_mem) {}
|
||||
};
|
||||
|
||||
#endif
|
564
lib/array_decl_plugin.cpp
Normal file
564
lib/array_decl_plugin.cpp
Normal file
|
@ -0,0 +1,564 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
array_decl_plugin.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
<abstract>
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-01-09
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include<sstream>
|
||||
#include"array_decl_plugin.h"
|
||||
#include"warning.h"
|
||||
#include"ast_pp.h"
|
||||
#include"ast_ll_pp.h"
|
||||
|
||||
array_decl_plugin::array_decl_plugin():
|
||||
m_store_sym("store"),
|
||||
m_select_sym("select"),
|
||||
m_const_sym("const"),
|
||||
m_default_sym("default"),
|
||||
m_map_sym("map"),
|
||||
m_set_union_sym("union"),
|
||||
m_set_intersect_sym("intersect"),
|
||||
m_set_difference_sym("difference"),
|
||||
m_set_complement_sym("complement"),
|
||||
m_set_subset_sym("subset"),
|
||||
m_array_ext_sym("array-ext"),
|
||||
m_as_array_sym("as-array") {
|
||||
}
|
||||
|
||||
#define ARRAY_SORT_STR "Array"
|
||||
|
||||
sort * array_decl_plugin::mk_sort(decl_kind k, unsigned num_parameters, parameter const * parameters) {
|
||||
SASSERT(k == ARRAY_SORT);
|
||||
if (num_parameters < 2) {
|
||||
m_manager->raise_exception("invalid array sort definition, invalid number of parameters");
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < num_parameters; i++) {
|
||||
if (!parameters[i].is_ast() || !is_sort(parameters[i].get_ast())) {
|
||||
m_manager->raise_exception("invalid array sort definition, parameter is not a sort");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
sort * range = to_sort(parameters[num_parameters - 1].get_ast());
|
||||
TRACE("array_decl_plugin_bug", tout << mk_pp(range, *m_manager) << "\n";);
|
||||
if (!range->is_infinite() && !range->is_very_big() && (1 == range->get_num_elements().size())) {
|
||||
return m_manager->mk_sort(symbol(ARRAY_SORT_STR), sort_info(m_family_id, ARRAY_SORT, 1,
|
||||
num_parameters, parameters));
|
||||
}
|
||||
bool is_infinite = false;
|
||||
bool is_very_big = false;
|
||||
for (unsigned i = 0; i < num_parameters; i++) {
|
||||
sort * s = to_sort(parameters[i].get_ast());
|
||||
if (s->is_infinite()) {
|
||||
is_infinite = true;
|
||||
}
|
||||
if (s->is_very_big()) {
|
||||
is_very_big = true;
|
||||
}
|
||||
}
|
||||
if (is_infinite) {
|
||||
return m_manager->mk_sort(symbol(ARRAY_SORT_STR), sort_info(m_family_id, ARRAY_SORT, num_parameters, parameters));
|
||||
}
|
||||
else if (is_very_big) {
|
||||
return m_manager->mk_sort(symbol(ARRAY_SORT_STR), sort_info(m_family_id, ARRAY_SORT, sort_size::mk_very_big(),
|
||||
num_parameters, parameters));
|
||||
}
|
||||
else {
|
||||
rational domain_sz(1);
|
||||
rational num_elements;
|
||||
for (unsigned i = 0; i < num_parameters - 1; i++) {
|
||||
domain_sz *= rational(to_sort(parameters[i].get_ast())->get_num_elements().size(),rational::ui64());
|
||||
}
|
||||
if (domain_sz <= rational(128)) {
|
||||
num_elements = rational(range->get_num_elements().size(),rational::ui64());
|
||||
num_elements = power(num_elements, static_cast<int>(domain_sz.get_int64()));
|
||||
}
|
||||
|
||||
if (domain_sz > rational(128) || !num_elements.is_uint64()) {
|
||||
// too many elements...
|
||||
return m_manager->mk_sort(symbol(ARRAY_SORT_STR),
|
||||
sort_info(m_family_id,
|
||||
ARRAY_SORT,
|
||||
sort_size::mk_very_big(),
|
||||
num_parameters,
|
||||
parameters));
|
||||
}
|
||||
else {
|
||||
return m_manager->mk_sort(symbol(ARRAY_SORT_STR), sort_info(m_family_id, ARRAY_SORT, num_elements.get_uint64(),
|
||||
num_parameters, parameters));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool array_decl_plugin::is_array_sort(sort* s) const {
|
||||
return m_family_id == s->get_family_id() && s->get_decl_kind() == ARRAY_SORT;
|
||||
}
|
||||
|
||||
|
||||
func_decl * array_decl_plugin::mk_const(sort * s, unsigned arity, sort * const * domain) {
|
||||
if (arity != 1) {
|
||||
m_manager->raise_exception("invalid const array definition, invalid domain size");
|
||||
return 0;
|
||||
}
|
||||
unsigned num_parameters = s->get_num_parameters();
|
||||
|
||||
if (num_parameters == 0) {
|
||||
m_manager->raise_exception("parameter mismatch");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// TBD check that range sort corresponds to last parameter.
|
||||
|
||||
parameter param(s);
|
||||
func_decl_info info(m_family_id, OP_CONST_ARRAY, 1, ¶m);
|
||||
info.m_private_parameters = true;
|
||||
return m_manager->mk_func_decl(m_const_sym, arity, domain, s, info);
|
||||
}
|
||||
|
||||
func_decl * array_decl_plugin::mk_map(func_decl* f, unsigned arity, sort* const* domain) {
|
||||
if (arity != f->get_arity()) {
|
||||
std::ostringstream buffer;
|
||||
buffer << "map expects to take as many arguments as the function being mapped, "
|
||||
<< "it was given " << arity << " but expects " << f->get_arity();
|
||||
m_manager->raise_exception(buffer.str().c_str());
|
||||
return 0;
|
||||
}
|
||||
if (arity == 0) {
|
||||
m_manager->raise_exception("don't use map on constants");
|
||||
return 0;
|
||||
}
|
||||
//
|
||||
// check that each domain[i] is an array sort
|
||||
// with the same domains and same ranges.
|
||||
// and that the ranges coincide with the domain of f.
|
||||
//
|
||||
unsigned dom_arity = get_array_arity(domain[0]);
|
||||
for (unsigned i = 0; i < arity; ++i) {
|
||||
if (!is_array_sort(domain[i])) {
|
||||
std::ostringstream buffer;
|
||||
buffer << "map expects an array sort as argument at position " << i;
|
||||
m_manager->raise_exception(buffer.str().c_str());
|
||||
return 0;
|
||||
}
|
||||
if (get_array_arity(domain[i]) != dom_arity) {
|
||||
std::ostringstream buffer;
|
||||
buffer << "map expects all arguments to have the same array domain, "
|
||||
<< "this is not the case for argument " << i;
|
||||
m_manager->raise_exception(buffer.str().c_str());
|
||||
return 0;
|
||||
}
|
||||
for (unsigned j = 0; j < dom_arity; ++j) {
|
||||
if (get_array_domain(domain[i],j) != get_array_domain(domain[0],j)) {
|
||||
std::ostringstream buffer;
|
||||
buffer << "map expects all arguments to have the same array domain, "
|
||||
<< "this is not the case for argument " << i;
|
||||
m_manager->raise_exception(buffer.str().c_str());
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (get_array_range(domain[i]) != f->get_domain(i)) {
|
||||
std::ostringstream buffer;
|
||||
buffer << "map expects the argument at position " << i
|
||||
<< " to have the array range the same as the function";
|
||||
m_manager->raise_exception(buffer.str().c_str());
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
vector<parameter> parameters;
|
||||
for (unsigned i = 0; i < dom_arity; ++i) {
|
||||
parameters.push_back(domain[0]->get_parameter(i));
|
||||
}
|
||||
parameters.push_back(parameter(f->get_range()));
|
||||
sort* range = mk_sort(ARRAY_SORT, parameters.size(), parameters.c_ptr());
|
||||
parameter param(f);
|
||||
func_decl_info info(m_family_id, OP_ARRAY_MAP, 1, ¶m);
|
||||
//
|
||||
// left_associative, right_associative, commutative are inherited.
|
||||
// m_injective is inherited, since:
|
||||
// forall x . g(f(x)) = x implies forall X . map(g)(map(f)(X)) = X
|
||||
// since map(g)(map(f)(X))[i] = g(f(X[i])) = X[i]
|
||||
//
|
||||
|
||||
info.set_right_associative(f->is_right_associative());
|
||||
info.set_left_associative(f->is_left_associative());
|
||||
info.set_commutative(f->is_commutative());
|
||||
info.set_injective(f->is_injective());
|
||||
return m_manager->mk_func_decl(m_map_sym, arity, domain, range, info);
|
||||
}
|
||||
|
||||
|
||||
func_decl * array_decl_plugin::mk_default(unsigned domain_size, sort * const * domain) {
|
||||
if (domain_size != 1) {
|
||||
m_manager->raise_exception("invalid default array definition, invalid domain size");
|
||||
return 0;
|
||||
}
|
||||
// check that domain[0] is an array sort.
|
||||
unsigned num_parameters = domain[0]->get_num_parameters();
|
||||
|
||||
if (num_parameters <= 1) {
|
||||
m_manager->raise_exception("parameter mismatch. There should be more than one parameter to defaults");
|
||||
return 0;
|
||||
}
|
||||
parameter param(domain[0]->get_parameter(num_parameters-1));
|
||||
if (!param.is_ast() || !is_sort(param.get_ast())) {
|
||||
m_manager->raise_exception("last parameter should be a sort");
|
||||
return 0;
|
||||
}
|
||||
sort * s = to_sort(param.get_ast());
|
||||
|
||||
return m_manager->mk_func_decl(m_default_sym, domain_size, domain, s,
|
||||
func_decl_info(m_family_id, OP_ARRAY_DEFAULT));
|
||||
}
|
||||
|
||||
|
||||
func_decl* array_decl_plugin::mk_select(unsigned arity, sort * const * domain) {
|
||||
if (arity <= 1) {
|
||||
m_manager->raise_exception("select takes at least two arguments");
|
||||
return 0;
|
||||
}
|
||||
sort * s = domain[0];
|
||||
unsigned num_parameters = s->get_num_parameters();
|
||||
parameter const* parameters = s->get_parameters();
|
||||
|
||||
if (num_parameters != arity) {
|
||||
m_manager->raise_exception("select requires as many arguments as the size of the domain");
|
||||
return 0;
|
||||
}
|
||||
if (domain[0] != s) {
|
||||
m_manager->raise_exception("first argument of select needs to be an array");
|
||||
return 0;
|
||||
}
|
||||
for (unsigned i = 0; i + 1 < num_parameters; ++i) {
|
||||
if (!parameters[i].is_ast() || domain[i+1] != parameters[i].get_ast()) {
|
||||
m_manager->raise_exception("domain sort and parameter do not match");
|
||||
UNREACHABLE();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return m_manager->mk_func_decl(m_select_sym, arity, domain, get_array_range(domain[0]),
|
||||
func_decl_info(m_family_id, OP_SELECT));
|
||||
}
|
||||
|
||||
func_decl * array_decl_plugin::mk_store(unsigned arity, sort * const * domain) {
|
||||
if (arity < 3) {
|
||||
m_manager->raise_exception("store takes at least 3 arguments");
|
||||
return 0;
|
||||
}
|
||||
sort * s = domain[0];
|
||||
unsigned num_parameters = s->get_num_parameters();
|
||||
parameter const * parameters = s->get_parameters();
|
||||
if (!is_array_sort(s)) {
|
||||
m_manager->raise_exception("store expects the first argument sort to be an array");
|
||||
UNREACHABLE();
|
||||
return 0;
|
||||
}
|
||||
if (arity != num_parameters+1) {
|
||||
std::ostringstream buffer;
|
||||
buffer << "store expects the first argument to be an array taking " << num_parameters+1
|
||||
<< ", instead it was passed " << (arity - 1) << "arguments";
|
||||
m_manager->raise_exception(buffer.str().c_str());
|
||||
UNREACHABLE();
|
||||
return 0;
|
||||
}
|
||||
for (unsigned i = 0; i < num_parameters; ++i) {
|
||||
if (!parameters[i].is_ast()) {
|
||||
m_manager->raise_exception("expecting sort parameter");
|
||||
return 0;
|
||||
}
|
||||
if (parameters[i].get_ast() != domain[i+1]) {
|
||||
m_manager->raise_exception("domain sort and parameter do not match");
|
||||
UNREACHABLE();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return m_manager->mk_func_decl(m_store_sym, arity, domain, domain[0],
|
||||
func_decl_info(m_family_id, OP_STORE));
|
||||
}
|
||||
|
||||
func_decl * array_decl_plugin::mk_array_ext_skolem(unsigned arity, sort * const * domain, unsigned i) {
|
||||
if (arity != 2 || domain[0] != domain[1]) {
|
||||
UNREACHABLE();
|
||||
return 0;
|
||||
}
|
||||
sort * s = domain[0];
|
||||
unsigned num_parameters = s->get_num_parameters();
|
||||
if (num_parameters == 0 || i >= num_parameters - 1) {
|
||||
UNREACHABLE();
|
||||
return 0;
|
||||
}
|
||||
sort * r = to_sort(s->get_parameter(i).get_ast());
|
||||
parameter param(s);
|
||||
return m_manager->mk_func_decl(m_array_ext_sym, arity, domain, r, func_decl_info(m_family_id, OP_ARRAY_EXT_SKOLEM, 1, ¶m));
|
||||
}
|
||||
|
||||
|
||||
bool array_decl_plugin::check_set_arguments(unsigned arity, sort * const * domain) {
|
||||
for (unsigned i = 0; i < arity; ++i) {
|
||||
if (domain[i] != domain[0]) {
|
||||
std::ostringstream buffer;
|
||||
buffer << "arguments " << 1 << " and " << (i+1) << " have different sorts";
|
||||
m_manager->raise_exception(buffer.str().c_str());
|
||||
return false;
|
||||
}
|
||||
if (domain[i]->get_family_id() != m_family_id) {
|
||||
std::ostringstream buffer;
|
||||
buffer << "argument " << (i+1) << " is not of array sort";
|
||||
m_manager->raise_exception(buffer.str().c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (arity > 0) {
|
||||
unsigned num_params = domain[0]->get_num_parameters();
|
||||
parameter const* params = domain[0]->get_parameters();
|
||||
if (1 >= num_params) {
|
||||
m_manager->raise_exception("expecting 2 or more parameters");
|
||||
UNREACHABLE();
|
||||
return false;
|
||||
}
|
||||
if (!params[num_params-1].is_ast()) {
|
||||
m_manager->raise_exception("expecting term parameters");
|
||||
UNREACHABLE();
|
||||
return false;
|
||||
}
|
||||
if (!is_sort(params[num_params-1].get_ast()) || !m_manager->is_bool(to_sort(params[num_params-1].get_ast()))) {
|
||||
m_manager->raise_exception("expecting boolean range");
|
||||
UNREACHABLE();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
func_decl * array_decl_plugin::mk_set_union(unsigned arity, sort * const * domain) {
|
||||
|
||||
if (arity == 0) {
|
||||
m_manager->raise_exception("union takes at least one argument");
|
||||
return 0;
|
||||
}
|
||||
sort * s = domain[0];
|
||||
if (!check_set_arguments(arity, domain)) {
|
||||
return 0;
|
||||
}
|
||||
parameter param(s);
|
||||
func_decl_info info(m_family_id, OP_SET_UNION, 1, ¶m);
|
||||
info.set_associative();
|
||||
info.set_commutative();
|
||||
info.set_idempotent();
|
||||
sort* domain2[2] = { domain[0], domain[0] };
|
||||
return m_manager->mk_func_decl(m_set_union_sym, 2, domain2, domain[0], info);
|
||||
}
|
||||
|
||||
func_decl * array_decl_plugin::mk_set_intersect(unsigned arity, sort * const * domain) {
|
||||
|
||||
if (arity == 0) {
|
||||
m_manager->raise_exception("intersection takes at least one argument");
|
||||
return 0;
|
||||
}
|
||||
if (!check_set_arguments(arity, domain)) {
|
||||
return 0;
|
||||
}
|
||||
func_decl_info info(m_family_id, OP_SET_INTERSECT);
|
||||
info.set_associative();
|
||||
info.set_commutative();
|
||||
info.set_idempotent();
|
||||
sort* domain2[2] = { domain[0], domain[0] };
|
||||
return m_manager->mk_func_decl(m_set_intersect_sym, 2, domain2, domain[0], info);
|
||||
}
|
||||
|
||||
func_decl * array_decl_plugin::mk_set_difference(unsigned arity, sort * const * domain) {
|
||||
if (arity != 2) {
|
||||
m_manager->raise_exception("set difference takes precisely two arguments");
|
||||
return 0;
|
||||
}
|
||||
if (!check_set_arguments(arity, domain)) {
|
||||
return 0;
|
||||
}
|
||||
return m_manager->mk_func_decl(m_set_difference_sym, arity, domain, domain[0],
|
||||
func_decl_info(m_family_id, OP_SET_DIFFERENCE));
|
||||
}
|
||||
|
||||
func_decl * array_decl_plugin::mk_set_complement(unsigned arity, sort * const * domain) {
|
||||
if (arity != 1) {
|
||||
m_manager->raise_exception("set complement takes one argument");
|
||||
return 0;
|
||||
}
|
||||
if (!check_set_arguments(arity, domain)) {
|
||||
return 0;
|
||||
}
|
||||
return m_manager->mk_func_decl(m_set_complement_sym, arity, domain, domain[0],
|
||||
func_decl_info(m_family_id, OP_SET_COMPLEMENT));
|
||||
}
|
||||
|
||||
func_decl * array_decl_plugin::mk_set_subset(unsigned arity, sort * const * domain) {
|
||||
if (arity != 2) {
|
||||
m_manager->raise_exception("subset takes two arguments");
|
||||
return 0;
|
||||
}
|
||||
if (!check_set_arguments(arity, domain)) {
|
||||
return 0;
|
||||
}
|
||||
sort * bool_sort = m_manager->mk_bool_sort();
|
||||
return m_manager->mk_func_decl(m_set_subset_sym, arity, domain, bool_sort,
|
||||
func_decl_info(m_family_id, OP_SET_SUBSET));
|
||||
}
|
||||
|
||||
func_decl * array_decl_plugin::mk_as_array(func_decl * f) {
|
||||
vector<parameter> parameters;
|
||||
for (unsigned i = 0; i < f->get_arity(); i++) {
|
||||
parameters.push_back(parameter(f->get_domain(i)));
|
||||
}
|
||||
parameters.push_back(parameter(f->get_range()));
|
||||
sort * s = mk_sort(ARRAY_SORT, parameters.size(), parameters.c_ptr());
|
||||
parameter param(f);
|
||||
func_decl_info info(m_family_id, OP_AS_ARRAY, 1, ¶m);
|
||||
return m_manager->mk_const_decl(m_as_array_sym, s, info);
|
||||
}
|
||||
|
||||
|
||||
func_decl * array_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters, parameter const * parameters,
|
||||
unsigned arity, sort * const * domain, sort * range) {
|
||||
switch (k) {
|
||||
case OP_SELECT:
|
||||
return mk_select(arity, domain);
|
||||
case OP_STORE:
|
||||
return mk_store(arity, domain);
|
||||
case OP_CONST_ARRAY: {
|
||||
if (num_parameters == 1 && parameters[0].is_ast() && is_sort(parameters[0].get_ast())) {
|
||||
sort * s = to_sort(parameters[0].get_ast());
|
||||
return mk_const(s, arity, domain);
|
||||
}
|
||||
else if (range != 0) {
|
||||
return mk_const(range, arity, domain);
|
||||
}
|
||||
else {
|
||||
m_manager->raise_exception("array operation requires one sort parameter (the array sort)");
|
||||
UNREACHABLE();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
case OP_ARRAY_MAP: {
|
||||
if (num_parameters != 1 || !parameters[0].is_ast() || !is_func_decl(parameters[0].get_ast())) {
|
||||
m_manager->raise_exception("array operation requires one function declaration parameter (the function to be mapped)");
|
||||
UNREACHABLE();
|
||||
return 0;
|
||||
}
|
||||
func_decl * f = to_func_decl(parameters[0].get_ast());
|
||||
return mk_map(f, arity, domain);
|
||||
}
|
||||
case OP_ARRAY_EXT_SKOLEM:
|
||||
if (num_parameters != 1 || !parameters[0].is_int()) {
|
||||
UNREACHABLE();
|
||||
return 0;
|
||||
}
|
||||
return mk_array_ext_skolem(arity, domain, parameters[0].get_int());
|
||||
case OP_ARRAY_DEFAULT:
|
||||
return mk_default(arity, domain);
|
||||
case OP_SET_UNION:
|
||||
return mk_set_union(arity, domain);
|
||||
case OP_SET_INTERSECT:
|
||||
return mk_set_intersect(arity, domain);
|
||||
case OP_SET_DIFFERENCE:
|
||||
return mk_set_difference(arity, domain);
|
||||
case OP_SET_COMPLEMENT:
|
||||
return mk_set_complement(arity, domain);
|
||||
case OP_SET_SUBSET:
|
||||
return mk_set_subset(arity, domain);
|
||||
case OP_AS_ARRAY: {
|
||||
if (num_parameters != 1 ||
|
||||
!parameters[0].is_ast() ||
|
||||
!is_func_decl(parameters[0].get_ast()) ||
|
||||
to_func_decl(parameters[0].get_ast())->get_arity() == 0) {
|
||||
TRACE("array_bug",
|
||||
tout << "num_parameters: " << num_parameters << std::endl;
|
||||
tout << "parameter.kind: " << parameters[0].is_int() << " " << parameters[0].is_ast() << " " << parameters[0].is_symbol() << "\n";
|
||||
tout << "as-array-bug: " << to_func_decl(parameters[0].get_ast())->get_name() << " " << to_func_decl(parameters[0].get_ast())->get_arity() << std::endl;);
|
||||
m_manager->raise_exception("as-array takes one parameter, a function declaration with arity greater than zero");
|
||||
UNREACHABLE();
|
||||
return 0;
|
||||
}
|
||||
func_decl * f = to_func_decl(parameters[0].get_ast());
|
||||
return mk_as_array(f);
|
||||
}
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void array_decl_plugin::get_sort_names(svector<builtin_name>& sort_names, symbol const & logic) {
|
||||
sort_names.push_back(builtin_name(ARRAY_SORT_STR, ARRAY_SORT));
|
||||
}
|
||||
|
||||
void array_decl_plugin::get_op_names(svector<builtin_name>& op_names, symbol const & logic) {
|
||||
op_names.push_back(builtin_name("store",OP_STORE));
|
||||
op_names.push_back(builtin_name("select",OP_SELECT));
|
||||
if (logic == symbol::null) {
|
||||
// none of the SMT2 logics support these extensions
|
||||
op_names.push_back(builtin_name("const",OP_CONST_ARRAY));
|
||||
op_names.push_back(builtin_name("map",OP_ARRAY_MAP));
|
||||
op_names.push_back(builtin_name("default",OP_ARRAY_DEFAULT));
|
||||
op_names.push_back(builtin_name("union",OP_SET_UNION));
|
||||
op_names.push_back(builtin_name("intersect",OP_SET_INTERSECT));
|
||||
op_names.push_back(builtin_name("difference",OP_SET_DIFFERENCE));
|
||||
op_names.push_back(builtin_name("complement",OP_SET_COMPLEMENT));
|
||||
op_names.push_back(builtin_name("subset",OP_SET_SUBSET));
|
||||
op_names.push_back(builtin_name("as-array", OP_AS_ARRAY));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
expr * array_decl_plugin::get_some_value(sort * s) {
|
||||
SASSERT(s->is_sort_of(m_family_id, ARRAY_SORT));
|
||||
sort * r = to_sort(s->get_parameter(s->get_num_parameters() - 1).get_ast());
|
||||
expr * v = m_manager->get_some_value(r);
|
||||
parameter p(s);
|
||||
return m_manager->mk_app(m_family_id, OP_CONST_ARRAY, 1, &p, 1, &v);
|
||||
}
|
||||
|
||||
bool array_decl_plugin::is_fully_interp(sort const * s) const {
|
||||
SASSERT(s->is_sort_of(m_family_id, ARRAY_SORT));
|
||||
unsigned sz = get_array_arity(s);
|
||||
for (unsigned i = 0; i < sz; i++) {
|
||||
if (!m_manager->is_fully_interp(get_array_domain(s, i)))
|
||||
return false;
|
||||
}
|
||||
return m_manager->is_fully_interp(get_array_range(s));
|
||||
}
|
||||
|
||||
bool array_util::is_as_array_tree(expr * n) {
|
||||
ptr_buffer<expr, 32> todo;
|
||||
todo.push_back(n);
|
||||
while (!todo.empty()) {
|
||||
expr * curr = todo.back();
|
||||
todo.pop_back();
|
||||
if (is_as_array(curr))
|
||||
continue;
|
||||
if (m_manager.is_ite(curr)) {
|
||||
todo.push_back(to_app(curr)->get_arg(1));
|
||||
todo.push_back(to_app(curr)->get_arg(2));
|
||||
continue;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
sort * array_util::mk_array_sort(unsigned arity, sort* const* domain, sort* range) {
|
||||
vector<parameter> params;
|
||||
for (unsigned i = 0; i < arity; ++i) {
|
||||
params.push_back(parameter(domain[i]));
|
||||
}
|
||||
params.push_back(parameter(range));
|
||||
return m_manager.mk_sort(m_fid, ARRAY_SORT, params.size(), params.c_ptr());
|
||||
}
|
170
lib/array_decl_plugin.h
Normal file
170
lib/array_decl_plugin.h
Normal file
|
@ -0,0 +1,170 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
array_decl_plugin.h
|
||||
|
||||
Abstract:
|
||||
|
||||
<abstract>
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-01-09.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _ARRAY_DECL_PLUGIN_H_
|
||||
#define _ARRAY_DECL_PLUGIN_H_
|
||||
|
||||
#include"ast.h"
|
||||
|
||||
|
||||
inline sort* get_array_range(sort const * s) {
|
||||
return to_sort(s->get_parameter(s->get_num_parameters() - 1).get_ast());
|
||||
}
|
||||
|
||||
inline unsigned get_array_arity(sort const * s) {
|
||||
return s->get_num_parameters() -1;
|
||||
}
|
||||
|
||||
inline sort* get_array_domain(sort const * s, unsigned idx) {
|
||||
return to_sort(s->get_parameter(idx).get_ast());
|
||||
}
|
||||
|
||||
enum array_sort_kind {
|
||||
ARRAY_SORT
|
||||
};
|
||||
|
||||
enum array_op_kind {
|
||||
OP_STORE,
|
||||
OP_SELECT,
|
||||
OP_CONST_ARRAY,
|
||||
OP_ARRAY_EXT_SKOLEM,
|
||||
OP_ARRAY_DEFAULT,
|
||||
OP_ARRAY_MAP,
|
||||
OP_SET_UNION,
|
||||
OP_SET_INTERSECT,
|
||||
OP_SET_DIFFERENCE,
|
||||
OP_SET_COMPLEMENT,
|
||||
OP_SET_SUBSET,
|
||||
OP_AS_ARRAY, // used for model construction
|
||||
LAST_ARRAY_OP
|
||||
};
|
||||
|
||||
class array_decl_plugin : public decl_plugin {
|
||||
symbol m_store_sym;
|
||||
symbol m_select_sym;
|
||||
symbol m_const_sym;
|
||||
symbol m_default_sym;
|
||||
symbol m_map_sym;
|
||||
symbol m_set_union_sym;
|
||||
symbol m_set_intersect_sym;
|
||||
symbol m_set_difference_sym;
|
||||
symbol m_set_complement_sym;
|
||||
symbol m_set_subset_sym;
|
||||
symbol m_array_ext_sym;
|
||||
symbol m_as_array_sym;
|
||||
|
||||
bool check_set_arguments(unsigned arity, sort * const * domain);
|
||||
|
||||
func_decl * mk_const(sort* ty, unsigned arity, sort * const * domain);
|
||||
|
||||
func_decl * mk_map(func_decl* f, unsigned arity, sort* const* domain);
|
||||
|
||||
func_decl * mk_default(unsigned arity, sort* const* domain);
|
||||
|
||||
func_decl * mk_select(unsigned arity, sort * const * domain);
|
||||
|
||||
func_decl * mk_store(unsigned arity, sort * const * domain);
|
||||
|
||||
func_decl * mk_array_ext_skolem(unsigned arity, sort * const * domain, unsigned i);
|
||||
|
||||
func_decl * mk_set_union(unsigned arity, sort * const * domain);
|
||||
|
||||
func_decl * mk_set_intersect(unsigned arity, sort * const * domain);
|
||||
|
||||
func_decl * mk_set_difference(unsigned arity, sort * const * domain);
|
||||
|
||||
func_decl * mk_set_complement(unsigned arity, sort * const * domain);
|
||||
|
||||
func_decl * mk_set_subset(unsigned arity, sort * const * domain);
|
||||
|
||||
func_decl * mk_as_array(func_decl * f);
|
||||
|
||||
bool is_array_sort(sort* s) const;
|
||||
public:
|
||||
array_decl_plugin();
|
||||
virtual ~array_decl_plugin() {}
|
||||
|
||||
virtual decl_plugin * mk_fresh() {
|
||||
return alloc(array_decl_plugin);
|
||||
}
|
||||
|
||||
//
|
||||
// Contract for sort:
|
||||
// parameters[0] - 1st dimension
|
||||
// ...
|
||||
// parameters[n-1] - nth dimension
|
||||
// parameters[n] - range
|
||||
//
|
||||
virtual sort * mk_sort(decl_kind k, unsigned num_parameters, parameter const * parameters);
|
||||
|
||||
//
|
||||
// Contract for func_decl:
|
||||
// parameters[0] - array sort
|
||||
// Contract for others:
|
||||
// no parameters
|
||||
virtual func_decl * mk_func_decl(decl_kind k, unsigned num_parameters, parameter const * parameters,
|
||||
unsigned arity, sort * const * domain, sort * range);
|
||||
|
||||
virtual void get_op_names(svector<builtin_name> & op_names, symbol const & logic);
|
||||
|
||||
virtual void get_sort_names(svector<builtin_name> & sort_names, symbol const & logic);
|
||||
|
||||
virtual expr * get_some_value(sort * s);
|
||||
|
||||
virtual bool is_fully_interp(sort const * s) const;
|
||||
};
|
||||
|
||||
class array_util {
|
||||
ast_manager & m_manager;
|
||||
family_id m_fid;
|
||||
public:
|
||||
array_util(ast_manager& m): m_manager(m), m_fid(m.get_family_id("array")) {}
|
||||
ast_manager & get_manager() const { return m_manager; }
|
||||
family_id get_family_id() const { return m_fid; }
|
||||
bool is_array(sort* s) const { return is_sort_of(s, m_fid, ARRAY_SORT);}
|
||||
bool is_array(expr* n) const { return is_array(m_manager.get_sort(n)); }
|
||||
bool is_select(expr* n) const { return is_app_of(n, m_fid, OP_SELECT); }
|
||||
bool is_store(expr* n) const { return is_app_of(n, m_fid, OP_STORE); }
|
||||
bool is_const(expr* n) const { return is_app_of(n, m_fid, OP_CONST_ARRAY); }
|
||||
bool is_map(expr* n) const { return is_app_of(n, m_fid, OP_ARRAY_MAP); }
|
||||
bool is_as_array(expr * n) const { return is_app_of(n, m_fid, OP_AS_ARRAY); }
|
||||
bool is_as_array_tree(expr * n);
|
||||
func_decl * get_as_array_func_decl(app * n) const { SASSERT(is_as_array(n)); return to_func_decl(n->get_decl()->get_parameter(0).get_ast()); }
|
||||
app * mk_map(func_decl * f, unsigned num_args, expr * const * args) {
|
||||
parameter p(f);
|
||||
return m_manager.mk_app(m_fid, OP_ARRAY_MAP, 1, &p, num_args, args);
|
||||
}
|
||||
app * mk_const_array(sort * s, expr * v) {
|
||||
parameter param(s);
|
||||
return m_manager.mk_app(m_fid, OP_CONST_ARRAY, 1, ¶m, 1, &v);
|
||||
}
|
||||
app * mk_empty_set(sort * s) {
|
||||
return mk_const_array(s, m_manager.mk_false());
|
||||
}
|
||||
app * mk_full_set(sort * s) {
|
||||
return mk_const_array(s, m_manager.mk_true());
|
||||
}
|
||||
|
||||
sort * mk_array_sort(sort* dom, sort* range) { return mk_array_sort(1, &dom, range); }
|
||||
|
||||
sort * mk_array_sort(unsigned arity, sort* const* domain, sort* range);
|
||||
};
|
||||
|
||||
|
||||
#endif /* _ARRAY_DECL_PLUGIN_H_ */
|
||||
|
206
lib/array_factory.cpp
Normal file
206
lib/array_factory.cpp
Normal file
|
@ -0,0 +1,206 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
array_factory.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
<abstract>
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-10-28.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#include"array_factory.h"
|
||||
#include"array_decl_plugin.h"
|
||||
#include"proto_model.h"
|
||||
#include"func_interp.h"
|
||||
#include"ast_pp.h"
|
||||
|
||||
func_decl * mk_aux_decl_for_array_sort(ast_manager & m, sort * s) {
|
||||
ptr_buffer<sort> domain;
|
||||
sort * range = get_array_range(s);
|
||||
unsigned arity = get_array_arity(s);
|
||||
for (unsigned i = 0; i < arity; i++) {
|
||||
domain.push_back(get_array_domain(s, i));
|
||||
}
|
||||
return m.mk_fresh_func_decl(symbol::null, symbol::null, arity, domain.c_ptr(), range);
|
||||
}
|
||||
|
||||
array_factory::array_factory(ast_manager & m, proto_model & md):
|
||||
struct_factory(m, m.get_family_id("array"), md) {
|
||||
}
|
||||
|
||||
/**
|
||||
\brieft Return as-array[f] where f is a fresh function symbol with the right domain and range for the array sort s.
|
||||
Store in fi the function interpretation for f.
|
||||
*/
|
||||
expr * array_factory::mk_array_interp(sort * s, func_interp * & fi) {
|
||||
func_decl * f = mk_aux_decl_for_array_sort(m_manager, s);
|
||||
fi = alloc(func_interp, m_manager, get_array_arity(s));
|
||||
m_model.register_decl(f, fi);
|
||||
parameter p[1] = { parameter(f) };
|
||||
expr * val = m_manager.mk_app(get_family_id(), OP_AS_ARRAY, 1, p);
|
||||
register_value(val);
|
||||
return val;
|
||||
}
|
||||
|
||||
void array_factory::get_some_args_for(sort * s, ptr_buffer<expr> & args) {
|
||||
unsigned arity = get_array_arity(s);
|
||||
for (unsigned i = 0; i < arity; i++) {
|
||||
sort * d = get_array_domain(s, i);
|
||||
expr * a = m_model.get_some_value(d);
|
||||
args.push_back(a);
|
||||
}
|
||||
}
|
||||
|
||||
expr * array_factory::get_some_value(sort * s) {
|
||||
TRACE("array_factory", tout << mk_pp(s, m_manager) << "\n";);
|
||||
value_set * set = 0;
|
||||
if (m_sort2value_set.find(s, set) && !set->empty())
|
||||
return *(set->begin());
|
||||
func_interp * fi;
|
||||
expr * val = mk_array_interp(s, fi);
|
||||
ptr_buffer<expr> args;
|
||||
get_some_args_for(s, args);
|
||||
fi->insert_entry(args.c_ptr(), m_model.get_some_value(get_array_range(s)));
|
||||
return val;
|
||||
}
|
||||
|
||||
bool array_factory::mk_two_diff_values_for(sort * s) {
|
||||
DEBUG_CODE({
|
||||
value_set * set = 0;
|
||||
SASSERT(!m_sort2value_set.find(s, set) || set->size() == 0);
|
||||
});
|
||||
expr_ref r1(m_manager);
|
||||
expr_ref r2(m_manager);
|
||||
sort * range = get_array_range(s);
|
||||
if (!m_model.get_some_values(range, r1, r2))
|
||||
return false; // failed... the range is probably unit.
|
||||
ptr_buffer<expr> args;
|
||||
get_some_args_for(s, args);
|
||||
func_interp * fi1;
|
||||
func_interp * fi2;
|
||||
mk_array_interp(s, fi1);
|
||||
mk_array_interp(s, fi2);
|
||||
fi1->insert_entry(args.c_ptr(), r1);
|
||||
fi2->insert_entry(args.c_ptr(), r2);
|
||||
DEBUG_CODE({
|
||||
value_set * set = 0;
|
||||
SASSERT(m_sort2value_set.find(s, set) && set->size() == 2);
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
bool array_factory::get_some_values(sort * s, expr_ref & v1, expr_ref & v2) {
|
||||
value_set * set = 0;
|
||||
if (!m_sort2value_set.find(s, set) || set->size() == 0) {
|
||||
if (!mk_two_diff_values_for(s))
|
||||
return false;
|
||||
}
|
||||
m_sort2value_set.find(s, set);
|
||||
SASSERT(set != 0);
|
||||
SASSERT(set->size() > 0);
|
||||
|
||||
if (set->size() == 1) {
|
||||
v1 = *(set->begin());
|
||||
v2 = get_fresh_value(s);
|
||||
return v2.get() != 0;
|
||||
}
|
||||
else {
|
||||
SASSERT(set->size() >= 2);
|
||||
value_set::iterator it = set->begin();
|
||||
v1 = *it;
|
||||
++it;
|
||||
v2 = *it;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// TODO: I have to check if the following procedure is really correct.
|
||||
// I'm supporting partial arrays where the "else" can be set later by the model_finder or model classes.
|
||||
// Projection functions may be also used.
|
||||
//
|
||||
// If projections are not used, then the following code should work if the "else" of a partial array
|
||||
// is set with the result of some entry.
|
||||
//
|
||||
expr * array_factory::get_fresh_value(sort * s) {
|
||||
value_set * set = get_value_set(s);
|
||||
if (set->empty()) {
|
||||
// easy case
|
||||
return get_some_value(s);
|
||||
}
|
||||
sort * range = get_array_range(s);
|
||||
expr * range_val = m_model.get_fresh_value(range);
|
||||
if (range_val != 0) {
|
||||
// easy case
|
||||
func_interp * fi;
|
||||
expr * val = mk_array_interp(s, fi);
|
||||
ptr_buffer<expr> args;
|
||||
get_some_args_for(s, args);
|
||||
fi->insert_entry(args.c_ptr(), range_val);
|
||||
return val;
|
||||
}
|
||||
else {
|
||||
TRACE("array_factory_bug", tout << "array fresh value: using fresh index, range: " << mk_pp(range, m_manager) << "\n";);
|
||||
expr_ref v1(m_manager);
|
||||
expr_ref v2(m_manager);
|
||||
if (m_model.get_some_values(range, v1, v2)) {
|
||||
// Claim: A is fresh if A[i1] = v1 and A[i2] = v2 where i1 and i2 are fresh values,
|
||||
// and v1 and v2 are distinct.
|
||||
//
|
||||
// Proof: let assume there is an Array A' such that A' = A.
|
||||
// Then A[i1] == A'[i1] and A[i2] == A'[i2]. Since, i1 and i2 are fresh,
|
||||
// A' does not have an entry for i1 or i2, So A'[i1] == A'[i2] == A'.m_else.
|
||||
// Thus, A[i1] == A[i2] which is a contradiction since v1 != v2 and A[i1] = v1 and A[i2] = v2.
|
||||
TRACE("array_factory_bug", tout << "v1: " << mk_pp(v1, m_manager) << " v2: " << mk_pp(v2, m_manager) << "\n";);
|
||||
ptr_buffer<expr> args1;
|
||||
ptr_buffer<expr> args2;
|
||||
bool found = false;
|
||||
unsigned arity = get_array_arity(s);
|
||||
for (unsigned i = 0; i < arity; i++) {
|
||||
sort * d = get_array_domain(s, i);
|
||||
if (!found) {
|
||||
expr * arg1 = m_model.get_fresh_value(d);
|
||||
expr * arg2 = m_model.get_fresh_value(d);
|
||||
if (arg1 != 0 && arg2 != 0) {
|
||||
found = true;
|
||||
args1.push_back(arg1);
|
||||
args2.push_back(arg2);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
expr * arg = m_model.get_some_value(d);
|
||||
args1.push_back(arg);
|
||||
args2.push_back(arg);
|
||||
}
|
||||
if (found) {
|
||||
func_interp * fi;
|
||||
expr * val = mk_array_interp(s, fi);
|
||||
fi->insert_entry(args1.c_ptr(), v1);
|
||||
fi->insert_entry(args2.c_ptr(), v2);
|
||||
return val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: use more expensive procedures to create a fresh array value.
|
||||
// Example: track the values used in the domain.
|
||||
|
||||
// Remark: in the current implementation, this function
|
||||
// will never fail, since if a type is finite, then
|
||||
// type_pred will be applied and get_fresh_value will not
|
||||
// need to be used.
|
||||
|
||||
// failed to create a fresh array value
|
||||
TRACE("array_factory_bug", tout << "failed to build fresh array value\n";);
|
||||
return 0;
|
||||
}
|
||||
|
45
lib/array_factory.h
Normal file
45
lib/array_factory.h
Normal file
|
@ -0,0 +1,45 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
array_factory.h
|
||||
|
||||
Abstract:
|
||||
|
||||
<abstract>
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-10-28.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _ARRAY_FACTORY_H_
|
||||
#define _ARRAY_FACTORY_H_
|
||||
|
||||
#include"struct_factory.h"
|
||||
|
||||
class func_interp;
|
||||
|
||||
func_decl * mk_aux_decl_for_array_sort(ast_manager & m, sort * s);
|
||||
|
||||
class array_factory : public struct_factory {
|
||||
expr * mk_array_interp(sort * s, func_interp * & fi);
|
||||
void get_some_args_for(sort * s, ptr_buffer<expr> & args);
|
||||
bool mk_two_diff_values_for(sort * s);
|
||||
public:
|
||||
array_factory(ast_manager & m, proto_model & md);
|
||||
|
||||
virtual ~array_factory() {}
|
||||
|
||||
virtual expr * get_some_value(sort * s);
|
||||
|
||||
virtual bool get_some_values(sort * s, expr_ref & v1, expr_ref & v2);
|
||||
|
||||
virtual expr * get_fresh_value(sort * s);
|
||||
};
|
||||
|
||||
#endif /* _ARRAY_FACTORY_H_ */
|
||||
|
162
lib/array_map.h
Normal file
162
lib/array_map.h
Normal file
|
@ -0,0 +1,162 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
array_map.h
|
||||
|
||||
Abstract:
|
||||
|
||||
A mapping for keys that can be mapped to unsigned integers.
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-01-03.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _ARRAY_MAP_H_
|
||||
#define _ARRAY_MAP_H_
|
||||
|
||||
#include"vector.h"
|
||||
#include"optional.h"
|
||||
|
||||
/**
|
||||
\brief Implements a mapping from Key to Data.
|
||||
|
||||
Plugin must provide the following functions:
|
||||
- void ins_eh(Key const & k, Data const & d);
|
||||
- void del_eh(Key const & k, Data const & d);
|
||||
- unsigned to_int(Key const & k);
|
||||
*/
|
||||
template<typename Key, typename Data, typename Plugin, bool CallDestructors=true>
|
||||
class array_map {
|
||||
|
||||
struct entry {
|
||||
Key m_key;
|
||||
Data m_data;
|
||||
unsigned m_timestamp;
|
||||
entry(Key const & k, Data const & d, unsigned t): m_key(k), m_data(d), m_timestamp(t) {}
|
||||
};
|
||||
|
||||
unsigned m_timestamp;
|
||||
unsigned m_garbage;
|
||||
unsigned m_non_garbage;
|
||||
static const unsigned m_gc_threshold = 10000;
|
||||
vector<optional<entry>, CallDestructors > m_map;
|
||||
Plugin m_plugin;
|
||||
|
||||
bool is_current(optional<entry> const& e) const {
|
||||
return e->m_timestamp == m_timestamp;
|
||||
}
|
||||
|
||||
optional<entry> const & get_core(Key const & k) const {
|
||||
unsigned id = m_plugin.to_int(k);
|
||||
if (id < m_map.size()) {
|
||||
optional<entry> const & e = m_map[id];
|
||||
if (e && is_current(e)) {
|
||||
return e;
|
||||
}
|
||||
}
|
||||
return optional<entry>::undef();
|
||||
}
|
||||
|
||||
void really_flush() {
|
||||
typename vector<optional<entry> >::iterator it = m_map.begin();
|
||||
typename vector<optional<entry> >::iterator end = m_map.end();
|
||||
for (; it != end; ++it) {
|
||||
optional<entry> & e = *it;
|
||||
if (e) {
|
||||
m_plugin.del_eh(e->m_key, e->m_data);
|
||||
e.set_invalid();
|
||||
}
|
||||
}
|
||||
m_garbage = 0;
|
||||
m_non_garbage = 0;
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
|
||||
array_map(Plugin const & p = Plugin()):m_timestamp(0), m_garbage(0), m_non_garbage(0), m_plugin(p) {}
|
||||
~array_map() { really_flush(); }
|
||||
|
||||
bool contains(Key const & k) const {
|
||||
return get_core(k);
|
||||
}
|
||||
|
||||
Data const & get(Key const & k) const {
|
||||
optional<entry> const & e = get_core(k);
|
||||
SASSERT(e);
|
||||
return e->m_data;
|
||||
}
|
||||
|
||||
void reset() {
|
||||
if (m_timestamp < UINT_MAX) {
|
||||
m_timestamp++;
|
||||
}
|
||||
else {
|
||||
really_flush();
|
||||
m_timestamp = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void insert(Key const & k, Data const & d) {
|
||||
unsigned id = m_plugin.to_int(k);
|
||||
if (id >= m_map.size()) {
|
||||
m_map.resize(id + 1, optional<entry>::undef());
|
||||
}
|
||||
|
||||
m_plugin.ins_eh(k, d);
|
||||
optional<entry> & e = m_map[id];
|
||||
if (e) {
|
||||
if (!is_current(e)) {
|
||||
--m_garbage;
|
||||
++m_non_garbage;
|
||||
}
|
||||
m_plugin.del_eh(e->m_key, e->m_data);
|
||||
}
|
||||
else {
|
||||
++m_non_garbage;
|
||||
}
|
||||
e = entry(k, d, m_timestamp);
|
||||
}
|
||||
|
||||
void erase(Key const & k) {
|
||||
unsigned id = m_plugin.to_int(k);
|
||||
if (id < m_map.size()) {
|
||||
optional<entry> & e = m_map[id];
|
||||
if (e) {
|
||||
m_plugin.del_eh(e->m_key, e->m_data);
|
||||
if (is_current(e)) {
|
||||
SASSERT(m_non_garbage > 0);
|
||||
--m_non_garbage;
|
||||
}
|
||||
else {
|
||||
SASSERT(m_garbage > 0);
|
||||
--m_garbage;
|
||||
}
|
||||
e.set_invalid();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void flush() {
|
||||
m_garbage += m_non_garbage;
|
||||
m_non_garbage = 0;
|
||||
if (m_garbage > m_gc_threshold) {
|
||||
really_flush();
|
||||
}
|
||||
else {
|
||||
reset();
|
||||
}
|
||||
}
|
||||
|
||||
void finalize() {
|
||||
really_flush();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif /* _ARRAY_MAP_H_ */
|
208
lib/array_property_expander.cpp
Normal file
208
lib/array_property_expander.cpp
Normal file
|
@ -0,0 +1,208 @@
|
|||
/*++
|
||||
Copyright (c) 2010 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
array_property_expander.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Expand array operations for the array property fragment formulas.
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2010-16-12
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#include"array_property_expander.h"
|
||||
#include"obj_hashtable.h"
|
||||
#include"var_subst.h"
|
||||
#include"array_decl_plugin.h"
|
||||
#include"for_each_expr.h"
|
||||
|
||||
array_property_expander::array_property_expander(ast_manager& m):
|
||||
m_manager(m) {
|
||||
}
|
||||
|
||||
namespace array_property_exp {
|
||||
class proc {
|
||||
ast_manager& m_manager;
|
||||
unsigned& m_offset;
|
||||
expr_ref_vector m_trail;
|
||||
family_id m_fid;
|
||||
array_util m_util;
|
||||
obj_map<expr, expr*> m_mem;
|
||||
|
||||
|
||||
void insert(expr* a, expr* b) {
|
||||
m_trail.push_back(b);
|
||||
m_mem.insert(a, b);
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
proc(ast_manager& m, unsigned& offset) :
|
||||
m_manager(m),
|
||||
m_offset(offset),
|
||||
m_trail(m),
|
||||
m_fid(m.get_family_id("array")),
|
||||
m_util(m)
|
||||
{}
|
||||
|
||||
expr* find(expr* e) {
|
||||
expr* result = 0;
|
||||
VERIFY(m_mem.find(e, result));
|
||||
return result;
|
||||
}
|
||||
|
||||
void operator()(var* n) { insert(n, n); }
|
||||
|
||||
void operator()(quantifier* q) {
|
||||
expr* e = find(q->get_expr());
|
||||
quantifier* q2 = m_manager.update_quantifier(q, e);
|
||||
insert(q, q2);
|
||||
}
|
||||
|
||||
void operator()(app* n) {
|
||||
ast_manager& m = m_manager;
|
||||
unsigned num_args = n->get_num_args();
|
||||
ptr_buffer<expr> args;
|
||||
for (unsigned i = 0; i < num_args; ++i) {
|
||||
args.push_back(find(n->get_arg(i)));
|
||||
}
|
||||
if (m_manager.is_eq(n) && m_util.is_array(args[0])) {
|
||||
visit_eq(n);
|
||||
return;
|
||||
}
|
||||
if (m_manager.is_distinct(n) && num_args > 0 && m_util.is_array(args[0])) {
|
||||
ptr_buffer<expr> eqs;
|
||||
for (unsigned i = 0; i < num_args; ++i) {
|
||||
for (unsigned j = i + 1; j < num_args; ++j) {
|
||||
eqs.push_back(m.mk_not(m.mk_eq(args[i], args[j])));
|
||||
}
|
||||
}
|
||||
insert(n, m.mk_and(eqs.size(), eqs.c_ptr()));
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_util.is_select(n)) {
|
||||
SASSERT(num_args > 0);
|
||||
|
||||
// select(store(A,i,v),j) -> ite(i = j, v, select(A,j))
|
||||
if (m_util.is_store(args[0])) {
|
||||
app* a = to_app(args[0]);
|
||||
expr* b = find(a->get_arg(0));
|
||||
expr* v = find(a->get_arg(a->get_num_args()-1));
|
||||
ptr_buffer<expr> eqs;
|
||||
SASSERT(num_args + 1 == a->get_num_args());
|
||||
for (unsigned i = 1; i < num_args; ++i) {
|
||||
eqs.push_back(m.mk_eq(args[i], find(a->get_arg(i))));
|
||||
}
|
||||
expr* r = m.mk_ite(m.mk_and(eqs.size(), eqs.c_ptr()), v, mk_select(b, num_args-1, args.c_ptr()+1));
|
||||
insert(n, r);
|
||||
return;
|
||||
}
|
||||
|
||||
// select(ite(a,b,c),i) -> ite(a, select(b,i), select(c, i))
|
||||
if (m.is_ite(args[0])) {
|
||||
app* k = to_app(args[0]);
|
||||
expr* a = k->get_arg(0);
|
||||
expr* b = mk_select(k->get_arg(1), args.size()-1, args.c_ptr()+1);
|
||||
expr* c = mk_select(k->get_arg(2), args.size()-1, args.c_ptr()+1);
|
||||
expr* r = m.mk_ite(a, b, c);
|
||||
insert(n, r);
|
||||
return;
|
||||
}
|
||||
|
||||
// select(map_f(A,B),i) -> f(select(A,i), select(B,i))
|
||||
if (m_util.is_map(args[0])) {
|
||||
app* a = to_app(args[0]);
|
||||
func_decl* f = a->get_decl();
|
||||
SASSERT(f->get_num_parameters() == 1);
|
||||
SASSERT(f->get_parameter(0).is_ast());
|
||||
SASSERT(is_func_decl(f->get_parameter(0).get_ast()));
|
||||
parameter p = f->get_parameter(0);
|
||||
func_decl* d = to_func_decl(p.get_ast());
|
||||
ptr_buffer<expr> args2;
|
||||
for (unsigned i = 0; i < a->get_num_args(); ++i) {
|
||||
args2.push_back(mk_select(find(a->get_arg(i)), args.size()-1, args.c_ptr()+1));
|
||||
}
|
||||
expr* r = m.mk_app(d, args2.size(), args2.c_ptr());
|
||||
insert(n, r);
|
||||
return;
|
||||
}
|
||||
|
||||
// select(const v, i) -> v
|
||||
if (m_util.is_const(args[0])) {
|
||||
insert(n, to_app(args[0])->get_arg(0));
|
||||
return;
|
||||
}
|
||||
}
|
||||
expr* r = m_manager.mk_app(n->get_decl(), args.size(), args.c_ptr());
|
||||
insert(n, r);
|
||||
}
|
||||
|
||||
private:
|
||||
void visit_eq(app* eq) {
|
||||
ast_manager& m = m_manager;
|
||||
SASSERT(m.is_eq(eq));
|
||||
sort* s = m.get_sort(eq->get_arg(0));
|
||||
SASSERT(is_sort_of(s, m_fid, ARRAY_SORT));
|
||||
// sort* rng = get_array_range(s);
|
||||
unsigned arity = get_array_arity(s);
|
||||
shift_vars sh(m);
|
||||
expr_ref e1(m), e2(m);
|
||||
sh(find(eq->get_arg(0)), arity, e1);
|
||||
sh(find(eq->get_arg(1)), arity, e2);
|
||||
expr_ref_vector args(m);
|
||||
buffer<symbol> names;
|
||||
ptr_buffer<sort> sorts;
|
||||
args.push_back(e1);
|
||||
for (unsigned i = 0; i < arity; ++i) {
|
||||
args.push_back(m.mk_var(i, get_array_domain(s, i)));
|
||||
sorts.push_back(get_array_domain(s, arity - i - 1));
|
||||
names.push_back(symbol(m_offset++));
|
||||
}
|
||||
e1 = mk_select(args.size(), args.c_ptr());
|
||||
args[0] = e2;
|
||||
e2 = mk_select(args.size(), args.c_ptr());
|
||||
e1 = m.mk_eq(e1, e2);
|
||||
|
||||
e1 = m.mk_quantifier(true, arity, sorts.c_ptr(), names.c_ptr(), e1, 1);
|
||||
insert(eq, e1);
|
||||
}
|
||||
|
||||
app* mk_select(unsigned n, expr* const* args) {
|
||||
return m_manager.mk_app(m_fid, OP_SELECT, 0, 0, n, args);
|
||||
}
|
||||
|
||||
app* mk_select(expr* a, unsigned n, expr* const* args) {
|
||||
ptr_buffer<expr> args2;
|
||||
args2.push_back(a);
|
||||
args2.append(n, args);
|
||||
return mk_select(n+1, args2.c_ptr());
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
void array_property_expander::operator()(unsigned num_fmls, expr* const* fmls, expr_ref_vector& result) {
|
||||
ast_manager& m = m_manager;
|
||||
unsigned offset = 0;
|
||||
for (unsigned i = 0; i < num_fmls; ++i) {
|
||||
bool change = false;
|
||||
expr_ref e(m);
|
||||
result.push_back(fmls[i]);
|
||||
do {
|
||||
array_property_exp::proc p(m, offset);
|
||||
e = result[i].get();
|
||||
for_each_expr(p, e);
|
||||
result[i] = p.find(e);
|
||||
change = e != result[i].get();
|
||||
}
|
||||
while (change);
|
||||
}
|
||||
}
|
||||
|
33
lib/array_property_expander.h
Normal file
33
lib/array_property_expander.h
Normal file
|
@ -0,0 +1,33 @@
|
|||
/*++
|
||||
Copyright (c) 2010 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
array_property_expander.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Expand array operations for the array property fragment formulas.
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2010-16-12
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _ARRAY_PROPERTY_EXPANDER_H_
|
||||
#define _ARRAY_PROPERTY_EXPANDER_H_
|
||||
|
||||
#include"ast.h"
|
||||
|
||||
class array_property_expander {
|
||||
ast_manager& m_manager;
|
||||
public:
|
||||
array_property_expander(ast_manager& m);
|
||||
void operator()(unsigned num_fmls, expr* const* fmls, expr_ref_vector& result);
|
||||
};
|
||||
|
||||
|
||||
#endif /* _ARRAY_PROPERTY_EXPANDER_H_ */
|
||||
|
103
lib/array_property_recognizer.cpp
Normal file
103
lib/array_property_recognizer.cpp
Normal file
|
@ -0,0 +1,103 @@
|
|||
/*++
|
||||
Copyright (c) 2010 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
array_property_recognizer.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
<abstract>
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2010-16-12
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#include"array_decl_plugin.h"
|
||||
#include"array_property_recognizer.h"
|
||||
#include"for_each_expr.h"
|
||||
|
||||
|
||||
array_property_recognizer::array_property_recognizer(ast_manager& m):
|
||||
m_manager(m) {}
|
||||
|
||||
namespace is_array_property_ns {
|
||||
struct bad {};
|
||||
class proc {
|
||||
ast_manager& m_manager;
|
||||
family_id m_fid;
|
||||
bool m_has_quantifier;
|
||||
|
||||
void check_array_sort(expr* n) {
|
||||
if (is_sort_of(m_manager.get_sort(n), m_fid, ARRAY_SORT)) {
|
||||
throw bad();
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
proc(ast_manager& m) :
|
||||
m_manager(m),
|
||||
m_fid(m.get_family_id("array")),
|
||||
m_has_quantifier(false) {}
|
||||
|
||||
bool has_quantifier() const { return m_has_quantifier; }
|
||||
|
||||
void operator()(var* n) {
|
||||
check_array_sort(n);
|
||||
}
|
||||
|
||||
void operator()(quantifier * ) {
|
||||
m_has_quantifier = true;
|
||||
}
|
||||
|
||||
void operator()(app* n) {
|
||||
unsigned num_args = n->get_num_args();
|
||||
if (m_manager.is_eq(n) || m_manager.is_distinct(n)) {
|
||||
return;
|
||||
}
|
||||
family_id fid = n->get_family_id();
|
||||
if (fid == m_fid) {
|
||||
switch(n->get_decl_kind()) {
|
||||
case OP_STORE:
|
||||
for (unsigned i = 1; i + 1 < num_args; ++i) {
|
||||
check_array_sort(n->get_arg(i));
|
||||
}
|
||||
return;
|
||||
case OP_SELECT:
|
||||
for (unsigned i = 1; i < num_args; ++i) {
|
||||
check_array_sort(n->get_arg(i));
|
||||
}
|
||||
return;
|
||||
case OP_CONST_ARRAY:
|
||||
case OP_ARRAY_MAP:
|
||||
return;
|
||||
default:
|
||||
throw bad();
|
||||
}
|
||||
}
|
||||
// arrays cannot be arguments of other functions.
|
||||
for (unsigned i = 0; i < num_args; ++i) {
|
||||
check_array_sort(n->get_arg(i));
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
bool array_property_recognizer::operator()(unsigned num_fmls, expr* const* fmls) {
|
||||
is_array_property_ns::proc p(m_manager);
|
||||
try {
|
||||
for (unsigned i = 0; i < num_fmls; ++i) {
|
||||
for_each_expr(p, fmls[i]);
|
||||
}
|
||||
}
|
||||
catch (is_array_property_ns::bad) {
|
||||
return false;
|
||||
}
|
||||
return p.has_quantifier();
|
||||
}
|
||||
|
||||
|
33
lib/array_property_recognizer.h
Normal file
33
lib/array_property_recognizer.h
Normal file
|
@ -0,0 +1,33 @@
|
|||
/*++
|
||||
Copyright (c) 2010 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
array_property_recognizer.h
|
||||
|
||||
Abstract:
|
||||
|
||||
<abstract>
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2010-16-12
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _ARRAY_PROPERTY_RECOGNIZER_H_
|
||||
#define _ARRAY_PROPERTY_RECOGNIZER_H_
|
||||
|
||||
#include"ast.h"
|
||||
|
||||
class array_property_recognizer {
|
||||
ast_manager& m_manager;
|
||||
public:
|
||||
array_property_recognizer(ast_manager& m);
|
||||
bool operator()(unsigned num_fmls, expr* const* fmls);
|
||||
};
|
||||
|
||||
|
||||
#endif /* _ARRAY_PROPERTY_RECOGNIZER_H_ */
|
||||
|
359
lib/array_rewriter.cpp
Normal file
359
lib/array_rewriter.cpp
Normal file
|
@ -0,0 +1,359 @@
|
|||
/*++
|
||||
Copyright (c) 2011 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
array_rewriter.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Basic rewriting rules for Arrays.
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo (leonardo) 2011-04-06
|
||||
|
||||
Notes:
|
||||
|
||||
--*/
|
||||
#include"array_rewriter.h"
|
||||
#include"ast_lt.h"
|
||||
#include"ast_pp.h"
|
||||
|
||||
void array_rewriter::updt_params(params_ref const & p) {
|
||||
m_sort_store = p.get_bool(":sort-store", false);
|
||||
m_expand_select_store = p.get_bool(":expand-select-store", false);
|
||||
}
|
||||
|
||||
void array_rewriter::get_param_descrs(param_descrs & r) {
|
||||
r.insert(":expand-select-store", CPK_BOOL, "(default: false) replace a (select (store ...) ...) term by an if-then-else term.");
|
||||
r.insert(":sort-store", CPK_BOOL, "(default: false) sort nested stores when the indices are known to be different.");
|
||||
}
|
||||
|
||||
br_status array_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result) {
|
||||
SASSERT(f->get_family_id() == get_fid());
|
||||
TRACE("array_rewriter", tout << mk_pp(f, m()) << "\n";
|
||||
for (unsigned i = 0; i < num_args; ++i) {
|
||||
tout << mk_pp(args[i], m()) << "\n";
|
||||
});
|
||||
switch (f->get_decl_kind()) {
|
||||
case OP_SELECT:
|
||||
return mk_select_core(num_args, args, result);
|
||||
case OP_STORE:
|
||||
return mk_store_core(num_args, args, result);
|
||||
case OP_ARRAY_MAP:
|
||||
SASSERT(f->get_num_parameters() == 1);
|
||||
SASSERT(f->get_parameter(0).is_ast());
|
||||
SASSERT(is_func_decl(f->get_parameter(0).get_ast()));
|
||||
return mk_map_core(to_func_decl(f->get_parameter(0).get_ast()), num_args, args, result);
|
||||
case OP_SET_UNION:
|
||||
return mk_set_union(num_args, args, result);
|
||||
case OP_SET_INTERSECT:
|
||||
return mk_set_intersect(num_args, args, result);
|
||||
case OP_SET_SUBSET:
|
||||
SASSERT(num_args == 2);
|
||||
return mk_set_subset(args[0], args[1], result);
|
||||
case OP_SET_COMPLEMENT:
|
||||
SASSERT(num_args == 1);
|
||||
return mk_set_complement(args[0], result);
|
||||
case OP_SET_DIFFERENCE:
|
||||
SASSERT(num_args == 2);
|
||||
return mk_set_difference(args[0], args[1], result);
|
||||
default:
|
||||
return BR_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
// l_true -- all equal
|
||||
// l_false -- at least one disequal
|
||||
// l_undef -- don't know
|
||||
template<bool CHECK_DISEQ>
|
||||
lbool array_rewriter::compare_args(unsigned num_args, expr * const * args1, expr * const * args2) {
|
||||
for (unsigned i = 0; i < num_args; i++) {
|
||||
if (args1[i] == args2[i])
|
||||
continue;
|
||||
if (CHECK_DISEQ && m().are_distinct(args1[i], args2[i]))
|
||||
return l_false;
|
||||
return l_undef;
|
||||
}
|
||||
return l_true;
|
||||
}
|
||||
|
||||
br_status array_rewriter::mk_store_core(unsigned num_args, expr * const * args, expr_ref & result) {
|
||||
SASSERT(num_args >= 3);
|
||||
|
||||
if (m_util.is_store(args[0])) {
|
||||
lbool r = m_sort_store ?
|
||||
compare_args<true>(num_args - 2, args + 1, to_app(args[0])->get_args() + 1) :
|
||||
compare_args<false>(num_args - 2, args + 1, to_app(args[0])->get_args() + 1);
|
||||
switch (r) {
|
||||
case l_true: {
|
||||
//
|
||||
// store(store(a,i,v),i,w) --> store(a,i,w)
|
||||
//
|
||||
ptr_buffer<expr> new_args;
|
||||
new_args.push_back(to_app(args[0])->get_arg(0));
|
||||
new_args.append(num_args-1, args+1);
|
||||
SASSERT(new_args.size() == num_args);
|
||||
result = m().mk_app(get_fid(), OP_STORE, num_args, new_args.c_ptr());
|
||||
return BR_DONE;
|
||||
}
|
||||
case l_false:
|
||||
SASSERT(m_sort_store);
|
||||
//
|
||||
// store(store(a,i,v),j,w) -> store(store(a,j,w),i,v)
|
||||
// if i, j are different, lt(i,j)
|
||||
//
|
||||
if (lex_lt(num_args-2, args+1, to_app(args[0])->get_args() + 1)) {
|
||||
ptr_buffer<expr> new_args;
|
||||
new_args.push_back(to_app(args[0])->get_arg(0));
|
||||
new_args.append(num_args-1, args+1);
|
||||
expr * nested_store = m().mk_app(get_fid(), OP_STORE, num_args, new_args.c_ptr());
|
||||
new_args.reset();
|
||||
new_args.push_back(nested_store);
|
||||
new_args.append(num_args - 1, to_app(args[0])->get_args() + 1);
|
||||
result = m().mk_app(get_fid(), OP_STORE, num_args, new_args.c_ptr());
|
||||
return BR_REWRITE2;
|
||||
}
|
||||
break;
|
||||
case l_undef:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// store(const(v),i,v) --> const(v)
|
||||
//
|
||||
if (m_util.is_const(args[0]) &&
|
||||
to_app(args[0])->get_arg(0) == args[num_args-1]) {
|
||||
result = args[0];
|
||||
return BR_DONE;
|
||||
}
|
||||
|
||||
expr * v = args[num_args-1];
|
||||
|
||||
//
|
||||
// store(a, i, select(a, i)) --> a
|
||||
//
|
||||
if (m_util.is_select(v) &&
|
||||
compare_args<false>(num_args-1, args, to_app(v)->get_args())) {
|
||||
result = args[0];
|
||||
return BR_DONE;
|
||||
}
|
||||
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
||||
br_status array_rewriter::mk_select_core(unsigned num_args, expr * const * args, expr_ref & result) {
|
||||
SASSERT(num_args >= 2);
|
||||
if (m_util.is_store(args[0])) {
|
||||
SASSERT(to_app(args[0])->get_num_args() == num_args+1);
|
||||
switch (compare_args<true>(num_args - 1, args+1, to_app(args[0])->get_args()+1)) {
|
||||
case l_true:
|
||||
// select(store(a, I, v), I) --> v
|
||||
result = to_app(args[0])->get_arg(num_args);
|
||||
return BR_DONE;
|
||||
case l_false: {
|
||||
// select(store(a, I, v), J) --> select(a, J) if I != J
|
||||
ptr_buffer<expr> new_args;
|
||||
new_args.push_back(to_app(args[0])->get_arg(0));
|
||||
new_args.append(num_args-1, args+1);
|
||||
result = m().mk_app(get_fid(), OP_SELECT, num_args, new_args.c_ptr());
|
||||
return BR_REWRITE1;
|
||||
}
|
||||
default:
|
||||
if (m_expand_select_store) {
|
||||
// select(store(a, I, v), J) --> ite(I=J, v, select(a, J))
|
||||
ptr_buffer<expr> new_args;
|
||||
new_args.push_back(to_app(args[0])->get_arg(0));
|
||||
new_args.append(num_args-1, args+1);
|
||||
expr * sel_a_j = m().mk_app(get_fid(), OP_SELECT, num_args, new_args.c_ptr());
|
||||
expr * v = to_app(args[0])->get_arg(num_args);
|
||||
ptr_buffer<expr> eqs;
|
||||
unsigned num_indices = num_args-1;
|
||||
for (unsigned i = 0; i < num_indices; i++) {
|
||||
eqs.push_back(m().mk_eq(to_app(args[0])->get_arg(i+1), args[i+1]));
|
||||
}
|
||||
if (num_indices == 1) {
|
||||
result = m().mk_ite(eqs[0], v, sel_a_j);
|
||||
return BR_REWRITE2;
|
||||
}
|
||||
else {
|
||||
result = m().mk_ite(m().mk_and(eqs.size(), eqs.c_ptr()), v, sel_a_j);
|
||||
return BR_REWRITE3;
|
||||
}
|
||||
}
|
||||
return BR_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_util.is_const(args[0])) {
|
||||
// select(const(v), I) --> v
|
||||
result = to_app(args[0])->get_arg(0);
|
||||
return BR_DONE;
|
||||
}
|
||||
|
||||
if (m_util.is_as_array(args[0])) {
|
||||
// select(as-array[f], I) --> f(I)
|
||||
func_decl * f = m_util.get_as_array_func_decl(to_app(args[0]));
|
||||
result = m().mk_app(f, num_args - 1, args + 1);
|
||||
return BR_REWRITE1;
|
||||
}
|
||||
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
||||
br_status array_rewriter::mk_map_core(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result) {
|
||||
SASSERT(num_args >= 0);
|
||||
bool is_store0 = m_util.is_store(args[0]);
|
||||
bool is_const0 = m_util.is_const(args[0]);
|
||||
if (num_args == 1) {
|
||||
//
|
||||
// map_f (store a j v) = (store (map_f a) j (f v))
|
||||
//
|
||||
if (is_store0) {
|
||||
app * store_expr = to_app(args[0]);
|
||||
unsigned num_args = store_expr->get_num_args();
|
||||
SASSERT(num_args >= 3);
|
||||
expr * a = store_expr->get_arg(0);
|
||||
expr * v = store_expr->get_arg(num_args-1);
|
||||
|
||||
ptr_buffer<expr> new_args;
|
||||
|
||||
new_args.push_back(m_util.mk_map(f, 1, &a)); // (map_f a)
|
||||
new_args.append(num_args - 2, store_expr->get_args() + 1); // j
|
||||
new_args.push_back(m().mk_app(f, v)); // (f v)
|
||||
|
||||
result = m().mk_app(get_fid(), OP_STORE, new_args.size(), new_args.c_ptr());
|
||||
return BR_REWRITE2;
|
||||
}
|
||||
|
||||
//
|
||||
// map_f (const v) = (const (f v))
|
||||
//
|
||||
if (is_const0) {
|
||||
expr * fv = m().mk_app(f, to_app(args[0])->get_arg(0));
|
||||
result = m_util.mk_const_array(m().get_sort(args[0]), fv);
|
||||
return BR_REWRITE2;
|
||||
}
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
||||
SASSERT(num_args > 1);
|
||||
|
||||
if (is_store0) {
|
||||
unsigned num_indices = to_app(args[0])->get_num_args() - 2;
|
||||
unsigned i;
|
||||
for (i = 1; i < num_args; i++) {
|
||||
if (!m_util.is_store(args[i]))
|
||||
break;
|
||||
unsigned j;
|
||||
for (j = 1; j < num_indices+1; j++) {
|
||||
if (to_app(args[0])->get_arg(j) != to_app(args[i])->get_arg(j))
|
||||
break;
|
||||
}
|
||||
if (j < num_indices+1)
|
||||
break;
|
||||
}
|
||||
//
|
||||
// map_f (store a_1 j v_1) ... (store a_n j v_n) --> (store (map_f a_1 ... a_n) j (f v_1 ... v_n))
|
||||
//
|
||||
if (i == num_args) {
|
||||
ptr_buffer<expr> arrays;
|
||||
ptr_buffer<expr> values;
|
||||
for (unsigned i = 0; i < num_args; i++) {
|
||||
arrays.push_back(to_app(args[i])->get_arg(0));
|
||||
values.push_back(to_app(args[i])->get_arg(num_indices+1));
|
||||
}
|
||||
ptr_buffer<expr> new_args;
|
||||
new_args.push_back(m_util.mk_map(f, arrays.size(), arrays.c_ptr()));
|
||||
new_args.append(num_indices, to_app(args[0])->get_args() + 1);
|
||||
new_args.push_back(m().mk_app(f, values.size(), values.c_ptr()));
|
||||
result = m().mk_app(get_fid(), OP_STORE, new_args.size(), new_args.c_ptr());
|
||||
return BR_REWRITE2;
|
||||
}
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
||||
if (is_const0) {
|
||||
unsigned i;
|
||||
for (i = 1; i < num_args; i++) {
|
||||
if (!m_util.is_const(args[i]))
|
||||
break;
|
||||
}
|
||||
if (i == num_args) {
|
||||
//
|
||||
// map_f (const v_1) ... (const v_n) = (const (f v_1 ... v_n))
|
||||
//
|
||||
ptr_buffer<expr> values;
|
||||
for (unsigned i = 0; i < num_args; i++) {
|
||||
values.push_back(to_app(args[i])->get_arg(0));
|
||||
}
|
||||
|
||||
expr * fv = m().mk_app(f, values.size(), values.c_ptr());
|
||||
parameter p(m().get_sort(args[0]));
|
||||
result = m().mk_app(get_fid(), OP_CONST_ARRAY, 1, &p, 1, &fv);
|
||||
return BR_REWRITE2;
|
||||
}
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
||||
void array_rewriter::mk_store(unsigned num_args, expr * const * args, expr_ref & result) {
|
||||
if (mk_store_core(num_args, args, result) == BR_FAILED)
|
||||
result = m().mk_app(get_fid(), OP_STORE, num_args, args);
|
||||
}
|
||||
|
||||
void array_rewriter::mk_select(unsigned num_args, expr * const * args, expr_ref & result) {
|
||||
if (mk_select_core(num_args, args, result) == BR_FAILED)
|
||||
result = m().mk_app(get_fid(), OP_SELECT, num_args, args);
|
||||
}
|
||||
|
||||
void array_rewriter::mk_map(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result) {
|
||||
if (mk_map_core(f, num_args, args, result) == BR_FAILED)
|
||||
result = m_util.mk_map(f, num_args, args);
|
||||
}
|
||||
|
||||
br_status array_rewriter::mk_set_union(unsigned num_args, expr * const * args, expr_ref & result) {
|
||||
SASSERT(num_args > 0);
|
||||
if (num_args == 1) {
|
||||
result = args[0];
|
||||
return BR_DONE;
|
||||
}
|
||||
SASSERT(num_args >= 2);
|
||||
br_status r = unsigned2br_status(num_args - 2);
|
||||
result = m_util.mk_map(m().mk_or_decl(), num_args, args);
|
||||
return r;
|
||||
}
|
||||
|
||||
br_status array_rewriter::mk_set_intersect(unsigned num_args, expr * const * args, expr_ref & result) {
|
||||
SASSERT(num_args > 0);
|
||||
if (num_args == 1) {
|
||||
result = args[0];
|
||||
return BR_DONE;
|
||||
}
|
||||
SASSERT(num_args >= 2);
|
||||
br_status r = unsigned2br_status(num_args - 2);
|
||||
result = m_util.mk_map(m().mk_and_decl(), num_args, args);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
br_status array_rewriter::mk_set_complement(expr * arg, expr_ref & result) {
|
||||
return mk_map_core(m().mk_not_decl(), 1, &arg, result);
|
||||
}
|
||||
|
||||
br_status array_rewriter::mk_set_difference(expr * arg1, expr * arg2, expr_ref & result) {
|
||||
expr * args[2] = { arg1, m_util.mk_map(m().mk_not_decl(), 1, &arg2) };
|
||||
result = m_util.mk_map(m().mk_and_decl(), 2, args);
|
||||
return BR_REWRITE2;
|
||||
}
|
||||
|
||||
br_status array_rewriter::mk_set_subset(expr * arg1, expr * arg2, expr_ref & result) {
|
||||
mk_set_difference(arg1, arg2, result);
|
||||
result = m().mk_eq(result.get(), m_util.mk_empty_set(m().get_sort(arg1)));
|
||||
return BR_REWRITE3;
|
||||
}
|
||||
|
65
lib/array_rewriter.h
Normal file
65
lib/array_rewriter.h
Normal file
|
@ -0,0 +1,65 @@
|
|||
/*++
|
||||
Copyright (c) 2011 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
array_rewriter.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Basic rewriting rules for Arrays.
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo (leonardo) 2011-04-06
|
||||
|
||||
Notes:
|
||||
|
||||
--*/
|
||||
#ifndef _ARRAY_REWRITER_H_
|
||||
#define _ARRAY_REWRITER_H_
|
||||
|
||||
#include"array_decl_plugin.h"
|
||||
#include"rewriter_types.h"
|
||||
#include"lbool.h"
|
||||
#include"params.h"
|
||||
|
||||
/**
|
||||
\brief Cheap rewrite rules for Arrays
|
||||
*/
|
||||
class array_rewriter {
|
||||
array_util m_util;
|
||||
bool m_sort_store;
|
||||
bool m_expand_select_store;
|
||||
template<bool CHECK_DISEQ>
|
||||
lbool compare_args(unsigned num_args, expr * const * args1, expr * const * args2);
|
||||
public:
|
||||
array_rewriter(ast_manager & m, params_ref const & p = params_ref()):
|
||||
m_util(m) {
|
||||
updt_params(p);
|
||||
}
|
||||
ast_manager & m() const { return m_util.get_manager(); }
|
||||
family_id get_fid() const { return m_util.get_family_id(); }
|
||||
|
||||
void updt_params(params_ref const & p);
|
||||
static void get_param_descrs(param_descrs & r);
|
||||
|
||||
br_status mk_app_core(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result);
|
||||
|
||||
br_status mk_store_core(unsigned num_args, expr * const * args, expr_ref & result);
|
||||
br_status mk_select_core(unsigned num_args, expr * const * args, expr_ref & result);
|
||||
br_status mk_map_core(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result);
|
||||
|
||||
void mk_store(unsigned num_args, expr * const * args, expr_ref & result);
|
||||
void mk_select(unsigned num_args, expr * const * args, expr_ref & result);
|
||||
void mk_map(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result);
|
||||
|
||||
// The following methods never return BR_FAILED
|
||||
br_status mk_set_union(unsigned num_args, expr * const * args, expr_ref & result);
|
||||
br_status mk_set_intersect(unsigned num_args, expr * const * args, expr_ref & result);
|
||||
br_status mk_set_complement(expr * arg, expr_ref & result);
|
||||
br_status mk_set_difference(expr * arg1, expr * arg2, expr_ref & result);
|
||||
br_status mk_set_subset(expr * arg1, expr * arg2, expr_ref & result);
|
||||
};
|
||||
|
||||
#endif
|
864
lib/array_simplifier_plugin.cpp
Normal file
864
lib/array_simplifier_plugin.cpp
Normal file
|
@ -0,0 +1,864 @@
|
|||
/*++
|
||||
Copyright (c) 2008 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
array_simplifier_plugin.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
<abstract>
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2008-05-05
|
||||
|
||||
Revision History:
|
||||
|
||||
Notes TODO:
|
||||
|
||||
Examine quadratic cost of simplification vs. model-based procedure.
|
||||
|
||||
Parameterize cache replacement strategy.
|
||||
Some parameters are hard-wired.
|
||||
|
||||
--*/
|
||||
|
||||
#include "array_simplifier_plugin.h"
|
||||
#include "ast_ll_pp.h"
|
||||
#include "ast_pp.h"
|
||||
|
||||
|
||||
array_simplifier_plugin::array_simplifier_plugin(
|
||||
ast_manager & m,
|
||||
basic_simplifier_plugin& s,
|
||||
simplifier& simp,
|
||||
theory_array_params const& p) :
|
||||
simplifier_plugin(symbol("array"),m),
|
||||
m_util(m),
|
||||
m_simp(s),
|
||||
m_simplifier(simp),
|
||||
m_params(p),
|
||||
m_store_cache_size(0)
|
||||
{}
|
||||
|
||||
|
||||
array_simplifier_plugin::~array_simplifier_plugin() {
|
||||
|
||||
select_cache::iterator it = m_select_cache.begin();
|
||||
select_cache::iterator end = m_select_cache.end();
|
||||
for ( ; it != end; ++it) {
|
||||
m_manager.dec_array_ref(it->m_key->size(), it->m_key->c_ptr());
|
||||
m_manager.dec_ref(it->m_value);
|
||||
dealloc(it->m_key);
|
||||
}
|
||||
|
||||
store_cache::iterator it2 = m_store_cache.begin();
|
||||
store_cache::iterator end2 = m_store_cache.end();
|
||||
for (; it2 != end2; ++it2) {
|
||||
m_manager.dec_ref(it->m_value);
|
||||
dealloc(it->m_key);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool array_simplifier_plugin::reduce(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result) {
|
||||
if (!m_params.m_array_simplify)
|
||||
return false;
|
||||
set_reduce_invoked();
|
||||
if (m_presimp)
|
||||
return false;
|
||||
#if _DEBUG
|
||||
for (unsigned i = 0; i < num_args && i < f->get_arity(); ++i) {
|
||||
SASSERT(m_manager.get_sort(args[i]) == f->get_domain(i));
|
||||
}
|
||||
#endif
|
||||
TRACE("array_simplifier", {
|
||||
tout << mk_pp(f, m_manager) << " ";
|
||||
for (unsigned i = 0; i < num_args; ++i) {
|
||||
tout << mk_pp(args[i], m_manager) << " ";
|
||||
}
|
||||
tout << "\n";
|
||||
}
|
||||
);
|
||||
SASSERT(f->get_family_id() == m_fid);
|
||||
switch(f->get_decl_kind()) {
|
||||
case OP_SELECT:
|
||||
mk_select(num_args, args, result);
|
||||
break;
|
||||
case OP_STORE:
|
||||
mk_store(f, num_args, args, result);
|
||||
break;
|
||||
case OP_SET_UNION: {
|
||||
sort* s = f->get_range();
|
||||
expr_ref empty(m_manager);
|
||||
mk_empty_set(s, empty);
|
||||
switch(num_args) {
|
||||
case 0:
|
||||
result = empty;
|
||||
break;
|
||||
case 1:
|
||||
result = args[0];
|
||||
break;
|
||||
default: {
|
||||
result = args[0];
|
||||
func_decl* f_or = m_manager.mk_or_decl();
|
||||
for (unsigned i = 1; i < num_args; ++i) {
|
||||
mk_map(f_or, result, args[i], result);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OP_SET_INTERSECT: {
|
||||
expr_ref full(m_manager);
|
||||
mk_full_set(f->get_range(), full);
|
||||
switch(num_args) {
|
||||
case 0:
|
||||
result = full;
|
||||
break;
|
||||
case 1:
|
||||
result = args[0];
|
||||
break;
|
||||
default: {
|
||||
result = args[0];
|
||||
func_decl* f_and = m_manager.mk_and_decl();
|
||||
for (unsigned i = 1; i < num_args; ++i) {
|
||||
mk_map(f_and, result, args[i], result);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
TRACE("array_simplifier", tout << "sort " << mk_pp(result.get(), m_manager) << "\n";);
|
||||
break;
|
||||
}
|
||||
case OP_SET_SUBSET: {
|
||||
SASSERT(num_args == 2);
|
||||
expr_ref diff(m_manager), emp(m_manager);
|
||||
mk_set_difference(num_args, args, diff);
|
||||
mk_empty_set(m_manager.get_sort(args[0]), emp);
|
||||
m_simp.mk_eq(diff.get(), emp.get(), result);
|
||||
break;
|
||||
}
|
||||
case OP_SET_COMPLEMENT: {
|
||||
SASSERT(num_args == 1);
|
||||
func_decl* f_not = m_manager.mk_not_decl();
|
||||
mk_map(f_not, args[0], result);
|
||||
break;
|
||||
}
|
||||
case OP_SET_DIFFERENCE: {
|
||||
SASSERT(num_args == 2);
|
||||
expr_ref r1(m_manager);
|
||||
mk_map(m_manager.mk_not_decl(), args[1], r1);
|
||||
mk_map(m_manager.mk_and_decl(), args[0], r1, result);
|
||||
break;
|
||||
}
|
||||
case OP_ARRAY_MAP: {
|
||||
SASSERT(f->get_num_parameters() == 1);
|
||||
SASSERT(f->get_parameter(0).is_ast());
|
||||
SASSERT(is_func_decl(f->get_parameter(0).get_ast()));
|
||||
//
|
||||
// map_d (store a j v) = (store (map_f a) v (d v))
|
||||
//
|
||||
if (num_args == 1 && is_store(args[0])) {
|
||||
app* store_expr = to_app(args[0]);
|
||||
unsigned num_args = store_expr->get_num_args();
|
||||
SASSERT(num_args >= 3);
|
||||
parameter p = f->get_parameter(0);
|
||||
func_decl* d = to_func_decl(p.get_ast());
|
||||
expr* a = store_expr->get_arg(0);
|
||||
expr* v = store_expr->get_arg(num_args-1);
|
||||
// expr*const* args = store_expr->get_args()+1;
|
||||
expr_ref r1(m_manager), r2(m_manager);
|
||||
ptr_vector<expr> new_args;
|
||||
|
||||
reduce(f, 1, &a, r1);
|
||||
m_simplifier.mk_app(d, 1, &v, r2);
|
||||
new_args.push_back(r1);
|
||||
for (unsigned i = 1; i + 1 < num_args; ++i) {
|
||||
new_args.push_back(store_expr->get_arg(i));
|
||||
}
|
||||
new_args.push_back(r2);
|
||||
mk_store(store_expr->get_decl(), num_args, new_args.c_ptr(), result);
|
||||
break;
|
||||
}
|
||||
|
||||
//
|
||||
// map_d (store a j v) (store b j w) = (store (map_f a b) j (d v w))
|
||||
//
|
||||
if (num_args > 1 && same_store(num_args, args)) {
|
||||
app* store_expr1 = to_app(args[0]);
|
||||
unsigned num_indices = store_expr1->get_num_args();
|
||||
SASSERT(num_indices >= 3);
|
||||
parameter p = f->get_parameter(0);
|
||||
func_decl* d = to_func_decl(p.get_ast());
|
||||
ptr_vector<expr> arrays;
|
||||
ptr_vector<expr> values;
|
||||
for (unsigned i = 0; i < num_args; ++i) {
|
||||
arrays.push_back(to_app(args[i])->get_arg(0));
|
||||
values.push_back(to_app(args[i])->get_arg(num_indices-1));
|
||||
}
|
||||
|
||||
expr_ref r1(m_manager), r2(m_manager);
|
||||
reduce(f, arrays.size(), arrays.c_ptr(), r1);
|
||||
m_simplifier.mk_app(d, values.size(), values.c_ptr(), r2);
|
||||
ptr_vector<expr> new_args;
|
||||
new_args.push_back(r1);
|
||||
for (unsigned i = 1; i + 1 < num_indices; ++i) {
|
||||
new_args.push_back(store_expr1->get_arg(i));
|
||||
}
|
||||
new_args.push_back(r2);
|
||||
mk_store(store_expr1->get_decl(), new_args.size(), new_args.c_ptr(), result);
|
||||
break;
|
||||
}
|
||||
//
|
||||
// map_d (const v) = (const (d v))
|
||||
//
|
||||
if (num_args == 1 && is_const_array(args[0])) {
|
||||
app* const_expr = to_app(args[0]);
|
||||
SASSERT(const_expr->get_num_args() == 1);
|
||||
parameter p = f->get_parameter(0);
|
||||
func_decl* d = to_func_decl(p.get_ast());
|
||||
expr* v = const_expr->get_arg(0);
|
||||
expr_ref r1(m_manager);
|
||||
|
||||
m_simplifier.mk_app(d, 1, &v, r1);
|
||||
expr* arg = r1.get();
|
||||
parameter param(f->get_range());
|
||||
result = m_manager.mk_app(m_fid, OP_CONST_ARRAY, 1, ¶m, 1, &arg);
|
||||
break;
|
||||
}
|
||||
//
|
||||
// map_d (const v) (const w) = (const (d v w))
|
||||
//
|
||||
if (num_args > 1 && all_const_array(num_args, args)) {
|
||||
parameter p = f->get_parameter(0);
|
||||
func_decl* d = to_func_decl(p.get_ast());
|
||||
ptr_vector<expr> values;
|
||||
for (unsigned i = 0; i < num_args; ++i) {
|
||||
values.push_back(to_app(args[i])->get_arg(0));
|
||||
}
|
||||
expr_ref r1(m_manager);
|
||||
|
||||
m_simplifier.mk_app(d, values.size(), values.c_ptr(), r1);
|
||||
expr* arg = r1.get();
|
||||
parameter param(f->get_range());
|
||||
result = m_manager.mk_app(m_fid, OP_CONST_ARRAY, 1, ¶m, 1, &arg);
|
||||
break;
|
||||
}
|
||||
result = m_manager.mk_app(f, num_args, args);
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
result = m_manager.mk_app(f, num_args, args);
|
||||
break;
|
||||
}
|
||||
TRACE("array_simplifier",
|
||||
tout << mk_pp(result.get(), m_manager) << "\n";);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool array_simplifier_plugin::same_store(unsigned num_args, expr* const* args) const {
|
||||
if (num_args == 0) {
|
||||
return true;
|
||||
}
|
||||
if (!is_store(args[0])) {
|
||||
return false;
|
||||
}
|
||||
SASSERT(to_app(args[0])->get_num_args() >= 3);
|
||||
unsigned num_indices = to_app(args[0])->get_num_args() - 2;
|
||||
for (unsigned i = 1; i < num_args; ++i) {
|
||||
if (!is_store(args[i])) {
|
||||
return false;
|
||||
}
|
||||
for (unsigned j = 1; j < num_indices + 1; ++j) {
|
||||
if (to_app(args[0])->get_arg(j) != to_app(args[i])->get_arg(j)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool array_simplifier_plugin::all_const_array(unsigned num_args, expr* const* args) const {
|
||||
bool is_const = true;
|
||||
for (unsigned i = 0; is_const && i < num_args; ++i) {
|
||||
is_const = is_const_array(args[i]);
|
||||
}
|
||||
return is_const;
|
||||
}
|
||||
|
||||
bool array_simplifier_plugin::all_values(unsigned num_args, expr* const* args) const {
|
||||
for (unsigned i = 0; i < num_args; ++i) {
|
||||
if (!m_manager.is_value(args[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool array_simplifier_plugin::lex_lt(unsigned num_args, expr* const* args1, expr* const* args2) {
|
||||
for (unsigned i = 0; i < num_args; ++i) {
|
||||
TRACE("array_simplifier",
|
||||
tout << mk_pp(args1[i], m_manager) << "\n";
|
||||
tout << mk_pp(args2[i], m_manager) << "\n";
|
||||
tout << args1[i]->get_id() << " " << args2[i]->get_id() << "\n";
|
||||
);
|
||||
|
||||
if (args1[i]->get_id() < args2[i]->get_id()) return true;
|
||||
if (args1[i]->get_id() > args2[i]->get_id()) return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void array_simplifier_plugin::get_stores(expr* n, unsigned& arity, expr*& m, ptr_vector<expr*const>& stores) {
|
||||
while (is_store(n)) {
|
||||
app* a = to_app(n);
|
||||
SASSERT(a->get_num_args() > 2);
|
||||
arity = a->get_num_args()-2;
|
||||
n = a->get_arg(0);
|
||||
stores.push_back(a->get_args()+1);
|
||||
}
|
||||
m = n;
|
||||
}
|
||||
|
||||
lbool array_simplifier_plugin::eq_default(expr* def, unsigned arity, unsigned num_st, expr*const* const* st) {
|
||||
for (unsigned i = 0; i < num_st; ++i) {
|
||||
if (st[i][arity] == def) {
|
||||
continue;
|
||||
}
|
||||
if (m_manager.is_value(st[i][arity]) && m_manager.is_value(def)) {
|
||||
return l_false;
|
||||
}
|
||||
return l_undef;
|
||||
}
|
||||
return l_true;
|
||||
}
|
||||
|
||||
bool array_simplifier_plugin::insert_table(expr* def, unsigned arity, unsigned num_st, expr*const* const* st, arg_table& table) {
|
||||
for (unsigned i = 0; i < num_st; ++i ) {
|
||||
for (unsigned j = 0; j < arity; ++j) {
|
||||
if (!m_manager.is_value(st[i][j])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
args_entry e(arity, st[i]);
|
||||
table.insert_if_not_there(e);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
lbool array_simplifier_plugin::eq_stores(expr* def, unsigned arity, unsigned num_st1, expr*const* const* st1, unsigned num_st2, expr*const* const* st2) {
|
||||
if (num_st1 == 0) {
|
||||
return eq_default(def, arity, num_st2, st2);
|
||||
}
|
||||
if (num_st2 == 0) {
|
||||
return eq_default(def, arity, num_st1, st1);
|
||||
}
|
||||
arg_table table1, table2;
|
||||
if (!insert_table(def, arity, num_st1, st1, table1)) {
|
||||
return l_undef;
|
||||
}
|
||||
if (!insert_table(def, arity, num_st2, st2, table2)) {
|
||||
return l_undef;
|
||||
}
|
||||
|
||||
arg_table::iterator it = table1.begin();
|
||||
arg_table::iterator end = table1.end();
|
||||
for (; it != end; ++it) {
|
||||
args_entry const & e1 = *it;
|
||||
args_entry e2;
|
||||
expr* v1 = e1.m_args[arity];
|
||||
if (table2.find(e1, e2)) {
|
||||
expr* v2 = e2.m_args[arity];
|
||||
if (v1 == v2) {
|
||||
table2.erase(e1);
|
||||
continue;
|
||||
}
|
||||
if (m_manager.is_value(v1) && m_manager.is_value(v2)) {
|
||||
return l_false;
|
||||
}
|
||||
return l_undef;
|
||||
}
|
||||
else if (m_manager.is_value(v1) && m_manager.is_value(def) && v1 != def) {
|
||||
return l_false;
|
||||
}
|
||||
}
|
||||
it = table2.begin();
|
||||
end = table2.end();
|
||||
for (; it != end; ++it) {
|
||||
args_entry const & e = *it;
|
||||
expr* v = e.m_args[arity];
|
||||
if (m_manager.is_value(v) && m_manager.is_value(def) && v != def) {
|
||||
return l_false;
|
||||
}
|
||||
}
|
||||
if (!table2.empty() || !table1.empty()) {
|
||||
return l_undef;
|
||||
}
|
||||
return l_true;
|
||||
}
|
||||
|
||||
|
||||
bool array_simplifier_plugin::reduce_eq(expr * lhs, expr * rhs, expr_ref & result) {
|
||||
set_reduce_invoked();
|
||||
expr* c1, *c2;
|
||||
ptr_vector<expr*const> st1, st2;
|
||||
unsigned arity = 0;
|
||||
get_stores(lhs, arity, c1, st1);
|
||||
get_stores(rhs, arity, c2, st2);
|
||||
if (is_const_array(c1) && is_const_array(c2)) {
|
||||
c1 = to_app(c1)->get_arg(0);
|
||||
c2 = to_app(c2)->get_arg(0);
|
||||
if (c1 == c2) {
|
||||
lbool eq = eq_stores(c1, arity, st1.size(), st1.c_ptr(), st2.size(), st2.c_ptr());
|
||||
TRACE("array_simplifier",
|
||||
tout << mk_pp(lhs, m_manager) << " = "
|
||||
<< mk_pp(rhs, m_manager) << " := " << eq << "\n";);
|
||||
switch(eq) {
|
||||
case l_false:
|
||||
result = m_manager.mk_false();
|
||||
return true;
|
||||
case l_true:
|
||||
result = m_manager.mk_true();
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (m_manager.is_value(c1) && m_manager.is_value(c2)) {
|
||||
result = m_manager.mk_false();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool array_simplifier_plugin::reduce_distinct(unsigned num_args, expr * const * args, expr_ref & result) {
|
||||
set_reduce_invoked();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
array_simplifier_plugin::const_select_result
|
||||
array_simplifier_plugin::mk_select_const(expr* m, app* index, expr_ref& result) {
|
||||
store_info* info = 0;
|
||||
expr* r = 0, *a = 0;
|
||||
if (!is_store(m)) {
|
||||
return NOT_CACHED;
|
||||
}
|
||||
if (!m_store_cache.find(m, info)) {
|
||||
return NOT_CACHED;
|
||||
}
|
||||
if (info->m_map.find(index, r)) {
|
||||
result = r;
|
||||
return FOUND_VALUE;
|
||||
}
|
||||
a = info->m_default.get();
|
||||
|
||||
//
|
||||
// Unfold and cache the store while searching for value of index.
|
||||
//
|
||||
while (is_store(a) && m_manager.is_value(to_app(a)->get_arg(1))) {
|
||||
app* b = to_app(a);
|
||||
app* c = to_app(b->get_arg(1));
|
||||
|
||||
if (!info->m_map.contains(c)) {
|
||||
info->m_map.insert(c, b->get_arg(2));
|
||||
m_manager.inc_ref(b->get_arg(2));
|
||||
++m_store_cache_size;
|
||||
}
|
||||
a = b->get_arg(0);
|
||||
info->m_default = a;
|
||||
|
||||
if (c == index) {
|
||||
result = b->get_arg(2);
|
||||
return FOUND_VALUE;
|
||||
}
|
||||
}
|
||||
result = info->m_default.get();
|
||||
return FOUND_DEFAULT;
|
||||
}
|
||||
|
||||
void array_simplifier_plugin::cache_store(unsigned num_stores, expr* store_term)
|
||||
{
|
||||
if (num_stores <= m_const_store_threshold) {
|
||||
return;
|
||||
}
|
||||
prune_store_cache();
|
||||
if (!m_store_cache.contains(store_term)) {
|
||||
store_info * info = alloc(store_info, m_manager, store_term);
|
||||
m_manager.inc_ref(store_term);
|
||||
m_store_cache.insert(store_term, info);
|
||||
TRACE("cache_store", tout << m_store_cache.size() << "\n";);
|
||||
++m_store_cache_size;
|
||||
}
|
||||
}
|
||||
|
||||
void array_simplifier_plugin::cache_select(unsigned num_args, expr * const * args, expr * result) {
|
||||
ptr_vector<expr> * entry = alloc(ptr_vector<expr>);
|
||||
entry->append(num_args, const_cast<expr**>(args));
|
||||
const select_cache::key_data & kd = m_select_cache.insert_if_not_there(entry, result);
|
||||
if (kd.m_key != entry) {
|
||||
dealloc(entry);
|
||||
return;
|
||||
}
|
||||
m_manager.inc_array_ref(num_args, args);
|
||||
m_manager.inc_ref(result);
|
||||
TRACE("cache_select", tout << m_select_cache.size() << "\n";);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void array_simplifier_plugin::prune_select_cache() {
|
||||
if (m_select_cache.size() > m_select_cache_max_size) {
|
||||
flush_select_cache();
|
||||
}
|
||||
}
|
||||
|
||||
void array_simplifier_plugin::prune_store_cache() {
|
||||
if (m_store_cache_size > m_store_cache_max_size) {
|
||||
flush_store_cache();
|
||||
}
|
||||
}
|
||||
|
||||
void array_simplifier_plugin::flush_select_cache() {
|
||||
select_cache::iterator it = m_select_cache.begin();
|
||||
select_cache::iterator end = m_select_cache.end();
|
||||
for (; it != end; ++it) {
|
||||
ptr_vector<expr> * e = (*it).m_key;
|
||||
m_manager.dec_array_ref(e->size(), e->begin());
|
||||
m_manager.dec_ref((*it).m_value);
|
||||
dealloc(e);
|
||||
}
|
||||
m_select_cache.reset();
|
||||
}
|
||||
|
||||
void array_simplifier_plugin::flush_store_cache() {
|
||||
store_cache::iterator it = m_store_cache.begin();
|
||||
store_cache::iterator end = m_store_cache.end();
|
||||
for (; it != end; ++it) {
|
||||
m_manager.dec_ref((*it).m_key);
|
||||
const_map::iterator mit = (*it).m_value->m_map.begin();
|
||||
const_map::iterator mend = (*it).m_value->m_map.end();
|
||||
for (; mit != mend; ++mit) {
|
||||
m_manager.dec_ref((*mit).m_value);
|
||||
}
|
||||
dealloc((*it).m_value);
|
||||
}
|
||||
m_store_cache.reset();
|
||||
m_store_cache_size = 0;
|
||||
}
|
||||
|
||||
|
||||
void array_simplifier_plugin::flush_caches() {
|
||||
flush_select_cache();
|
||||
flush_store_cache();
|
||||
}
|
||||
|
||||
void array_simplifier_plugin::mk_set_difference(unsigned num_args, expr * const * args, expr_ref & result) {
|
||||
SASSERT(num_args == 2);
|
||||
result = m_manager.mk_app(m_fid, OP_SET_DIFFERENCE, 0, 0, num_args, args);
|
||||
}
|
||||
|
||||
void array_simplifier_plugin::mk_empty_set(sort* ty, expr_ref & result) {
|
||||
parameter param(ty);
|
||||
expr* args[1] = { m_manager.mk_false() };
|
||||
result = m_manager.mk_app(m_fid, OP_CONST_ARRAY, 1, ¶m, 1, args);
|
||||
}
|
||||
|
||||
void array_simplifier_plugin::mk_full_set(sort* ty, expr_ref & result) {
|
||||
parameter param(ty);
|
||||
expr* args[1] = { m_manager.mk_true() };
|
||||
result = m_manager.mk_app(m_fid, OP_CONST_ARRAY, 1, ¶m, 1, args);
|
||||
}
|
||||
|
||||
|
||||
bool array_simplifier_plugin::same_args(unsigned num_args, expr * const * args1, expr * const * args2) {
|
||||
for (unsigned i = 0; i < num_args; ++i) {
|
||||
if (args1[i] != args2[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void array_simplifier_plugin::mk_store(func_decl* f, unsigned num_args, expr * const * args, expr_ref & result) {
|
||||
|
||||
SASSERT(num_args >= 3);
|
||||
|
||||
expr* arg0 = args[0];
|
||||
expr* argn = args[num_args-1];
|
||||
|
||||
//
|
||||
// store(store(a,i,v),i,w) = store(a,i,w)
|
||||
//
|
||||
if (is_store(arg0) &&
|
||||
same_args(num_args-2, args+1, to_app(arg0)->get_args()+1)) {
|
||||
expr_ref_buffer new_args(m_manager);
|
||||
new_args.push_back(to_app(arg0)->get_arg(0));
|
||||
for (unsigned i = 1; i < num_args; ++i) {
|
||||
new_args.push_back(args[i]);
|
||||
}
|
||||
reduce(f, num_args, new_args.c_ptr(), result);
|
||||
TRACE("array_simplifier", tout << mk_pp(result.get(), m_manager) << "\n";);
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// store(const(v),i,v) = const(v)
|
||||
//
|
||||
if (is_const_array(arg0) &&
|
||||
to_app(arg0)->get_arg(0) == args[num_args-1]) {
|
||||
result = arg0;
|
||||
TRACE("array_simplifier", tout << mk_pp(result.get(), m_manager) << "\n";);
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// store(a, i, select(a, i)) = a
|
||||
//
|
||||
if (is_select(argn) &&
|
||||
(to_app(argn)->get_num_args() == num_args - 1) &&
|
||||
same_args(num_args-1, args, to_app(argn)->get_args())) {
|
||||
TRACE("dummy_store", tout << "dummy store simplified mk_store(\n";
|
||||
for (unsigned i = 0; i < num_args; i++) ast_ll_pp(tout, m_manager, args[i]);
|
||||
tout << ") =====>\n";
|
||||
ast_ll_pp(tout, m_manager, arg0););
|
||||
result = arg0;
|
||||
TRACE("array_simplifier", tout << mk_pp(result.get(), m_manager) << "\n";);
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// store(store(a,i,v),j,w) -> store(store(a,j,w),i,v)
|
||||
// if i, j are values, i->get_id() < j->get_id()
|
||||
//
|
||||
if (m_params.m_array_canonize_simplify &&
|
||||
is_store(arg0) &&
|
||||
all_values(num_args-2, args+1) &&
|
||||
all_values(num_args-2, to_app(arg0)->get_args()+1) &&
|
||||
lex_lt(num_args-2, args+1, to_app(arg0)->get_args()+1)) {
|
||||
expr* const* args2 = to_app(arg0)->get_args();
|
||||
expr_ref_buffer new_args(m_manager);
|
||||
new_args.push_back(args2[0]);
|
||||
for (unsigned i = 1; i < num_args; ++i) {
|
||||
new_args.push_back(args[i]);
|
||||
}
|
||||
reduce(f, num_args, new_args.c_ptr(), result);
|
||||
new_args.reset();
|
||||
new_args.push_back(result);
|
||||
for (unsigned i = 1; i < num_args; ++i) {
|
||||
new_args.push_back(args2[i]);
|
||||
}
|
||||
result = m_manager.mk_app(m_fid, OP_STORE, num_args, new_args.c_ptr());
|
||||
TRACE("array_simplifier", tout << mk_pp(result.get(), m_manager) << "\n";);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
result = m_manager.mk_app(m_fid, OP_STORE, num_args, args);
|
||||
TRACE("array_simplifier", tout << "default: " << mk_pp(result.get(), m_manager) << "\n";);
|
||||
|
||||
}
|
||||
|
||||
void array_simplifier_plugin::mk_select_as_array(unsigned num_args, expr * const * args, expr_ref & result) {
|
||||
SASSERT(is_as_array(args[0]));
|
||||
func_decl * f = get_as_array_func_decl(to_app(args[0]));
|
||||
result = m_manager.mk_app(f, num_args - 1, args+1);
|
||||
}
|
||||
|
||||
void array_simplifier_plugin::mk_select_as_array_tree(unsigned num_args, expr * const * args, expr_ref & result) {
|
||||
SASSERT(is_as_array_tree(args[0]));
|
||||
SASSERT(m_manager.is_ite(args[0]));
|
||||
ptr_buffer<app, 32> todo;
|
||||
obj_map<app, app *> cache;
|
||||
app_ref_buffer trail(m_manager);
|
||||
todo.push_back(to_app(args[0]));
|
||||
while (!todo.empty()) {
|
||||
app * curr = todo.back();
|
||||
SASSERT(m_manager.is_ite(curr));
|
||||
expr * branches[2] = {0, 0};
|
||||
bool visited = true;
|
||||
for (unsigned i = 0; i < 2; i++) {
|
||||
expr * arg = curr->get_arg(i+1);
|
||||
if (is_as_array(arg)) {
|
||||
branches[i] = m_manager.mk_app(get_as_array_func_decl(to_app(arg)), num_args - 1, args+1);
|
||||
}
|
||||
else {
|
||||
SASSERT(m_manager.is_ite(arg));
|
||||
app * new_arg = 0;
|
||||
if (!cache.find(to_app(arg), new_arg)) {
|
||||
todo.push_back(to_app(arg));
|
||||
visited = false;
|
||||
}
|
||||
else {
|
||||
branches[i] = new_arg;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (visited) {
|
||||
todo.pop_back();
|
||||
app * new_curr = m_manager.mk_ite(curr->get_arg(0), branches[0], branches[1]);
|
||||
trail.push_back(new_curr);
|
||||
cache.insert(curr, new_curr);
|
||||
}
|
||||
}
|
||||
SASSERT(cache.contains(to_app(args[0])));
|
||||
app * r = 0;
|
||||
cache.find(to_app(args[0]), r);
|
||||
result = r;
|
||||
}
|
||||
|
||||
void array_simplifier_plugin::mk_select(unsigned num_args, expr * const * args, expr_ref & result) {
|
||||
expr * r = 0;
|
||||
|
||||
if (is_as_array(args[0])) {
|
||||
mk_select_as_array(num_args, args, result);
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_as_array_tree(args[0])) {
|
||||
mk_select_as_array_tree(num_args, args, result);
|
||||
return;
|
||||
}
|
||||
|
||||
bool is_const_select = num_args == 2 && m_manager.is_value(args[1]);
|
||||
app* const_index = is_const_select?to_app(args[1]):0;
|
||||
unsigned num_const_stores = 0;
|
||||
expr_ref tmp(m_manager);
|
||||
expr* args2[2];
|
||||
if (is_const_select) {
|
||||
switch(mk_select_const(args[0], const_index, tmp)) {
|
||||
case NOT_CACHED:
|
||||
break;
|
||||
case FOUND_VALUE:
|
||||
TRACE("mk_select", tout << "found value\n"; ast_ll_pp(tout, m_manager, tmp.get()); );
|
||||
result = tmp.get();
|
||||
// value of select is stored under result.
|
||||
return;
|
||||
case FOUND_DEFAULT:
|
||||
args2[0] = tmp.get();
|
||||
args2[1] = args[1];
|
||||
args = args2;
|
||||
is_const_select = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
SASSERT(num_args > 0);
|
||||
ptr_vector<expr> & entry = m_tmp2;
|
||||
entry.reset();
|
||||
entry.append(num_args, args);
|
||||
expr * entry0 = entry[0];
|
||||
SASSERT(m_todo.empty());
|
||||
m_todo.push_back(entry0);
|
||||
while (!m_todo.empty()) {
|
||||
expr * m = m_todo.back();
|
||||
TRACE("array_simplifier", tout << mk_bounded_pp(m, m_manager) << "\n";);
|
||||
if (is_store(m)) {
|
||||
expr * nested_array = to_app(m)->get_arg(0);
|
||||
expr * else_branch = 0;
|
||||
entry[0] = nested_array;
|
||||
if (is_const_select) {
|
||||
if (m_manager.is_value(to_app(m)->get_arg(1))) {
|
||||
app* const_index2 = to_app(to_app(m)->get_arg(1));
|
||||
//
|
||||
// we found the value, all other stores are different.
|
||||
// there is no need to recurse.
|
||||
//
|
||||
if (const_index == const_index2) {
|
||||
result = to_app(m)->get_arg(2);
|
||||
cache_store(num_const_stores, args[0]);
|
||||
m_todo.reset();
|
||||
return;
|
||||
}
|
||||
++num_const_stores;
|
||||
}
|
||||
else {
|
||||
is_const_select = false;
|
||||
}
|
||||
}
|
||||
if (m_select_cache.find(&entry, else_branch)) {
|
||||
expr_ref_buffer eqs(m_manager);
|
||||
for (unsigned i = 1; i < num_args ; ++i) {
|
||||
expr * a = args[i];
|
||||
expr * b = to_app(m)->get_arg(i);
|
||||
expr_ref eq(m_manager);
|
||||
m_simp.mk_eq(a, b, eq);
|
||||
eqs.push_back(eq.get());
|
||||
}
|
||||
expr_ref cond(m_manager);
|
||||
m_simp.mk_and(eqs.size(), eqs.c_ptr(), cond);
|
||||
expr * then_branch = to_app(m)->get_arg(num_args);
|
||||
if (m_manager.is_true(cond.get())) {
|
||||
result = then_branch;
|
||||
}
|
||||
else if (m_manager.is_false(cond.get())) {
|
||||
result = else_branch;
|
||||
}
|
||||
else {
|
||||
m_simp.mk_ite(cond.get(), then_branch, else_branch, result);
|
||||
}
|
||||
entry[0] = m;
|
||||
cache_select(entry.size(), entry.c_ptr(), result.get());
|
||||
m_todo.pop_back();
|
||||
}
|
||||
else {
|
||||
m_todo.push_back(nested_array);
|
||||
}
|
||||
}
|
||||
else if (is_const_array(m)) {
|
||||
entry[0] = m;
|
||||
cache_select(entry.size(), entry.c_ptr(), to_app(m)->get_arg(0));
|
||||
m_todo.pop_back();
|
||||
}
|
||||
else {
|
||||
entry[0] = m;
|
||||
TRACE("array_simplifier", {
|
||||
for (unsigned i = 0; i < entry.size(); ++i) {
|
||||
tout << mk_bounded_pp(entry[i], m_manager) << ": "
|
||||
<< mk_bounded_pp(m_manager.get_sort(entry[i]), m_manager) << "\n";
|
||||
}}
|
||||
);
|
||||
r = m_manager.mk_app(m_fid, OP_SELECT, 0, 0, entry.size(), entry.c_ptr());
|
||||
cache_select(entry.size(), entry.c_ptr(), r);
|
||||
m_todo.pop_back();
|
||||
}
|
||||
}
|
||||
cache_store(num_const_stores, args[0]);
|
||||
entry[0] = entry0;
|
||||
#ifdef Z3DEBUG
|
||||
bool f =
|
||||
#endif
|
||||
m_select_cache.find(&entry, r);
|
||||
SASSERT(f);
|
||||
result = r;
|
||||
prune_select_cache();
|
||||
prune_store_cache();
|
||||
TRACE("mk_select",
|
||||
for (unsigned i = 0; i < num_args; i++) {
|
||||
ast_ll_pp(tout, m_manager, args[i]); tout << "\n";
|
||||
};
|
||||
tout << "is_store: " << is_store(args[0]) << "\n";
|
||||
ast_ll_pp(tout, m_manager, r););
|
||||
}
|
||||
|
||||
|
||||
void array_simplifier_plugin::mk_map(func_decl* f, expr* a, expr* b, expr_ref& result) {
|
||||
expr* exprs[2] = { a, b };
|
||||
parameter param(f);
|
||||
result = m_manager.mk_app(m_fid, OP_ARRAY_MAP, 1, ¶m, 2, exprs );
|
||||
}
|
||||
|
||||
void array_simplifier_plugin::mk_map(func_decl* f, expr* a, expr_ref& result) {
|
||||
parameter param(f);
|
||||
result = m_manager.mk_app(m_fid, OP_ARRAY_MAP, 1, ¶m, 1, &a );
|
||||
}
|
||||
|
||||
|
154
lib/array_simplifier_plugin.h
Normal file
154
lib/array_simplifier_plugin.h
Normal file
|
@ -0,0 +1,154 @@
|
|||
/*++
|
||||
Copyright (c) 2008 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
array_simplifier_plugin.h
|
||||
|
||||
Abstract:
|
||||
|
||||
<abstract>
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2008-05-05
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _ARRAY_SIMPLIFIER_PLUGIN_H_
|
||||
#define _ARRAY_SIMPLIFIER_PLUGIN_H_
|
||||
|
||||
#include"ast.h"
|
||||
#include"map.h"
|
||||
#include"array_decl_plugin.h"
|
||||
#include"simplifier_plugin.h"
|
||||
#include"basic_simplifier_plugin.h"
|
||||
#include"theory_array_params.h"
|
||||
#include"simplifier.h"
|
||||
#include"obj_hashtable.h"
|
||||
#include"lbool.h"
|
||||
|
||||
class array_simplifier_plugin : public simplifier_plugin {
|
||||
|
||||
typedef ptr_vector<expr> entry;
|
||||
|
||||
struct entry_hash_proc {
|
||||
unsigned operator()(ptr_vector<expr> * entry) const {
|
||||
return get_exprs_hash(entry->size(), entry->begin(), 0xbeef1010);
|
||||
}
|
||||
};
|
||||
|
||||
struct entry_eq_proc {
|
||||
bool operator()(ptr_vector<expr> * entry1, ptr_vector<expr> * entry2) const {
|
||||
if (entry1->size() != entry2->size()) return false;
|
||||
return compare_arrays(entry1->begin(), entry2->begin(), entry1->size());
|
||||
}
|
||||
};
|
||||
|
||||
typedef map<entry *, expr *, entry_hash_proc, entry_eq_proc> select_cache;
|
||||
|
||||
struct args_entry {
|
||||
unsigned m_arity;
|
||||
expr* const* m_args;
|
||||
args_entry(unsigned a, expr* const* args) : m_arity(a), m_args(args) {}
|
||||
args_entry() : m_arity(0), m_args(0) {}
|
||||
};
|
||||
|
||||
struct args_entry_hash_proc {
|
||||
unsigned operator()(args_entry const& e) const {
|
||||
return get_exprs_hash(e.m_arity, e.m_args, 0xbeef1010);
|
||||
}
|
||||
};
|
||||
struct args_entry_eq_proc {
|
||||
bool operator()(args_entry const& e1, args_entry const& e2) const {
|
||||
if (e1.m_arity != e2.m_arity) return false;
|
||||
return compare_arrays(e1.m_args, e2.m_args, e1.m_arity);
|
||||
}
|
||||
};
|
||||
typedef hashtable<args_entry, args_entry_hash_proc, args_entry_eq_proc> arg_table;
|
||||
|
||||
array_util m_util;
|
||||
basic_simplifier_plugin& m_simp;
|
||||
simplifier& m_simplifier;
|
||||
theory_array_params const& m_params;
|
||||
select_cache m_select_cache;
|
||||
ptr_vector<expr> m_tmp;
|
||||
ptr_vector<expr> m_tmp2;
|
||||
ptr_vector<expr> m_todo;
|
||||
static const unsigned m_select_cache_max_size = 100000;
|
||||
typedef obj_map<expr, expr*> const_map;
|
||||
class store_info {
|
||||
store_info();
|
||||
store_info(store_info const&);
|
||||
public:
|
||||
const_map m_map;
|
||||
expr_ref m_default;
|
||||
store_info(ast_manager& m, expr* d): m_default(d, m) {}
|
||||
};
|
||||
|
||||
typedef obj_map<expr, store_info*> store_cache;
|
||||
store_cache m_store_cache;
|
||||
unsigned m_store_cache_size;
|
||||
static const unsigned m_store_cache_max_size = 10000;
|
||||
static const unsigned m_const_store_threshold = 5;
|
||||
enum const_select_result {
|
||||
NOT_CACHED,
|
||||
FOUND_DEFAULT,
|
||||
FOUND_VALUE
|
||||
};
|
||||
|
||||
|
||||
public:
|
||||
array_simplifier_plugin(ast_manager & m, basic_simplifier_plugin& s, simplifier& simp, theory_array_params const& p);
|
||||
virtual ~array_simplifier_plugin();
|
||||
|
||||
virtual bool reduce(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result);
|
||||
|
||||
virtual bool reduce_eq(expr * lhs, expr * rhs, expr_ref & result);
|
||||
|
||||
virtual bool reduce_distinct(unsigned num_args, expr * const * args, expr_ref & result);
|
||||
|
||||
virtual void flush_caches();
|
||||
|
||||
private:
|
||||
bool is_select(expr* n) const { return m_util.is_select(n); }
|
||||
bool is_store(expr * n) const { return m_util.is_store(n); }
|
||||
bool is_const_array(expr * n) const { return m_util.is_const(n); }
|
||||
bool is_as_array(expr * n) const { return m_util.is_as_array(n); }
|
||||
bool is_as_array_tree(expr * n) { return m_util.is_as_array_tree(n); }
|
||||
func_decl * get_as_array_func_decl(app * n) const { return m_util.get_as_array_func_decl(n); }
|
||||
void mk_select_as_array(unsigned num_args, expr * const * args, expr_ref & result);
|
||||
void mk_select_as_array_tree(unsigned num_args, expr * const * args, expr_ref & result);
|
||||
bool is_enumerated(expr* n, expr_ref& c, ptr_vector<expr>& keys, ptr_vector<expr>& vals);
|
||||
const_select_result mk_select_const(expr* m, app* index, expr_ref& result);
|
||||
void cache_store(unsigned num_stores, expr* nested_store);
|
||||
void cache_select(unsigned num_args, expr * const * args, expr * result);
|
||||
void prune_select_cache();
|
||||
void prune_store_cache();
|
||||
void flush_select_cache();
|
||||
void flush_store_cache();
|
||||
void mk_set_difference(unsigned num_args, expr * const * args, expr_ref & result);
|
||||
void mk_empty_set(sort* ty, expr_ref & result);
|
||||
void mk_full_set(sort* ty, expr_ref & result);
|
||||
void mk_select(unsigned num_args, expr * const * args, expr_ref & result);
|
||||
void mk_store(func_decl* f, unsigned num_args, expr * const * args, expr_ref & result);
|
||||
void mk_map(func_decl* f, expr* a, expr* b, expr_ref & result);
|
||||
void mk_map(func_decl* f, expr* a, expr_ref & result);
|
||||
bool same_args(unsigned num_args, expr * const * args1, expr * const * args2);
|
||||
|
||||
void get_stores(expr* n, unsigned& arity, expr*& m, ptr_vector<expr*const>& stores);
|
||||
lbool eq_default(expr* def, unsigned arity, unsigned num_st, expr*const* const* st);
|
||||
bool insert_table(expr* def, unsigned arity, unsigned num_st, expr*const* const* st, arg_table& table);
|
||||
lbool eq_stores(expr* def, unsigned arity, unsigned num_st1, expr*const* const* st1, unsigned num_st2, expr*const* const* st2);
|
||||
|
||||
bool same_store(unsigned num_args, expr* const* args) const;
|
||||
bool all_const_array(unsigned num_args, expr* const* args) const;
|
||||
bool all_values(unsigned num_args, expr* const* args) const;
|
||||
bool lex_lt(unsigned num_args, expr* const* args1, expr* const* args2);
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif /* _ARRAY_SIMPLIFIER_PLUGIN_H_ */
|
||||
|
1494
lib/asserted_formulas.cpp
Normal file
1494
lib/asserted_formulas.cpp
Normal file
File diff suppressed because it is too large
Load diff
200
lib/asserted_formulas.h
Normal file
200
lib/asserted_formulas.h
Normal file
|
@ -0,0 +1,200 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
asserted_formulas.h
|
||||
|
||||
Abstract:
|
||||
|
||||
<abstract>
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-06-11.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _ASSERTED_FORMULAS_H_
|
||||
#define _ASSERTED_FORMULAS_H_
|
||||
|
||||
#include"front_end_params.h"
|
||||
#include"simplifier.h"
|
||||
#include"basic_simplifier_plugin.h"
|
||||
#include"static_features.h"
|
||||
#include"macro_manager.h"
|
||||
#include"macro_finder.h"
|
||||
#include"defined_names.h"
|
||||
#include"solver_plugin.h"
|
||||
#include"maximise_ac_sharing.h"
|
||||
#include"bit2int.h"
|
||||
#include"qe.h"
|
||||
#include"statistics.h"
|
||||
#include"user_rewriter.h"
|
||||
|
||||
class arith_simplifier_plugin;
|
||||
class bv_simplifier_plugin;
|
||||
|
||||
class asserted_formulas {
|
||||
ast_manager & m_manager;
|
||||
front_end_params & m_params;
|
||||
simplifier m_pre_simplifier;
|
||||
subst_simplifier m_simplifier;
|
||||
basic_simplifier_plugin * m_bsimp;
|
||||
bv_simplifier_plugin * m_bvsimp;
|
||||
defined_names m_defined_names;
|
||||
static_features m_static_features;
|
||||
expr_ref_vector m_asserted_formulas; // formulas asserted by user
|
||||
proof_ref_vector m_asserted_formula_prs; // proofs for the asserted formulas.
|
||||
unsigned m_asserted_qhead;
|
||||
|
||||
expr_map m_subst;
|
||||
ptr_vector<app> m_vars; // domain of m_subst
|
||||
unsigned m_vars_qhead;
|
||||
|
||||
expr_mark m_forbidden;
|
||||
ptr_vector<app> m_forbidden_vars;
|
||||
|
||||
macro_manager m_macro_manager;
|
||||
scoped_ptr<macro_finder> m_macro_finder;
|
||||
|
||||
typedef plugin_manager<solver_plugin> solver_plugins;
|
||||
solver_plugins m_solver_plugins;
|
||||
|
||||
bit2int m_bit2int;
|
||||
|
||||
maximise_bv_sharing m_bv_sharing;
|
||||
|
||||
user_rewriter m_user_rewriter;
|
||||
|
||||
bool m_inconsistent;
|
||||
qe::expr_quant_elim_star1 m_quant_elim;
|
||||
|
||||
struct scope {
|
||||
unsigned m_asserted_formulas_lim;
|
||||
unsigned m_vars_lim;
|
||||
unsigned m_forbidden_vars_lim;
|
||||
bool m_inconsistent_old;
|
||||
};
|
||||
svector<scope> m_scopes;
|
||||
volatile bool m_cancel_flag;
|
||||
|
||||
void setup_simplifier_plugins(simplifier & s, basic_simplifier_plugin * & bsimp, arith_simplifier_plugin * & asimp, bv_simplifier_plugin * & bvsimp);
|
||||
bool trivial_solve(expr * lhs, expr * rhs, app_ref & var, expr_ref & subst, proof_ref& pr);
|
||||
bool is_pos_literal(expr * n);
|
||||
bool is_neg_literal(expr * n);
|
||||
bool solve_ite_definition_core(expr * lhs1, expr * rhs1, expr * lhs2, expr * rhs2, expr * cond, app_ref & var, expr_ref & subst);
|
||||
bool solve_ite_definition(expr * arg1, expr * arg2, expr * arg3, app_ref & var, expr_ref & subst);
|
||||
bool solve_core(expr * n, app_ref & var, expr_ref & subst, proof_ref& pr);
|
||||
bool solve_core();
|
||||
void solve();
|
||||
void reduce_asserted_formulas();
|
||||
void swap_asserted_formulas(expr_ref_vector & new_exprs, proof_ref_vector & new_prs);
|
||||
void find_macros_core();
|
||||
void find_macros();
|
||||
void expand_macros();
|
||||
void apply_demodulators();
|
||||
void apply_quasi_macros();
|
||||
void nnf_cnf();
|
||||
bool apply_eager_bit_blaster();
|
||||
bool apply_user_rewriter();
|
||||
void infer_patterns();
|
||||
void eliminate_term_ite();
|
||||
void reduce_and_solve();
|
||||
void flush_cache() { m_pre_simplifier.reset(); m_simplifier.reset(); }
|
||||
void restore_subst(unsigned old_size);
|
||||
void restore_forbidden_vars(unsigned old_size);
|
||||
void set_eliminate_and(bool flag);
|
||||
void propagate_values();
|
||||
void propagate_booleans();
|
||||
bool pull_cheap_ite_trees();
|
||||
bool pull_nested_quantifiers();
|
||||
void push_assertion(expr * e, proof * pr, expr_ref_vector & result, proof_ref_vector & result_prs);
|
||||
void context_simplifier();
|
||||
void strong_context_simplifier();
|
||||
void eliminate_and();
|
||||
void refine_inj_axiom();
|
||||
bool cheap_quant_fourier_motzkin();
|
||||
bool quant_elim();
|
||||
bool apply_der_core();
|
||||
void apply_der();
|
||||
void apply_distribute_forall();
|
||||
bool apply_bit2int();
|
||||
void lift_ite();
|
||||
bool elim_bvs_from_quantifiers();
|
||||
void ng_lift_ite();
|
||||
#ifdef Z3DEBUG
|
||||
bool check_well_sorted() const;
|
||||
#endif
|
||||
unsigned get_total_size() const;
|
||||
bool has_bv() const;
|
||||
void max_bv_sharing();
|
||||
bool canceled() { return m_cancel_flag; }
|
||||
|
||||
public:
|
||||
asserted_formulas(ast_manager & m, front_end_params & p);
|
||||
~asserted_formulas();
|
||||
|
||||
void setup();
|
||||
void assert_expr(expr * e, proof * in_pr);
|
||||
void assert_expr(expr * e);
|
||||
void reset();
|
||||
void set_cancel_flag(bool f);
|
||||
void push_scope();
|
||||
void pop_scope(unsigned num_scopes);
|
||||
bool inconsistent() const { return m_inconsistent; }
|
||||
proof * get_inconsistency_proof() const;
|
||||
void reduce();
|
||||
unsigned get_num_formulas() const { return m_asserted_formulas.size(); }
|
||||
unsigned get_formulas_last_level() const;
|
||||
unsigned get_qhead() const { return m_asserted_qhead; }
|
||||
void commit();
|
||||
expr * get_formula(unsigned idx) const { return m_asserted_formulas.get(idx); }
|
||||
proof * get_formula_proof(unsigned idx) const { return m_manager.proofs_enabled() ? m_asserted_formula_prs.get(idx) : 0; }
|
||||
expr * const * get_formulas() const { return m_asserted_formulas.c_ptr(); }
|
||||
proof * const * get_formula_proofs() const { return m_asserted_formula_prs.c_ptr(); }
|
||||
void init(unsigned num_formulas, expr * const * formulas, proof * const * prs);
|
||||
void register_simplifier_plugin(simplifier_plugin * p) { m_simplifier.register_plugin(p); }
|
||||
simplifier & get_simplifier() { return m_simplifier; }
|
||||
void set_user_rewriter(void* ctx, user_rewriter::fn* rw) { m_user_rewriter.set_rewriter(ctx, rw); }
|
||||
void get_assertions(ptr_vector<expr> & result);
|
||||
bool empty() const { return m_asserted_formulas.empty(); }
|
||||
void collect_static_features();
|
||||
void display(std::ostream & out) const;
|
||||
void display_ll(std::ostream & out, ast_mark & pp_visited) const;
|
||||
void collect_statistics(statistics & st) const;
|
||||
// TODO: improve precision of the following method.
|
||||
bool has_quantifiers() const { return m_simplifier.visited_quantifier(); /* approximation */ }
|
||||
|
||||
// -----------------------------------
|
||||
//
|
||||
// Macros
|
||||
//
|
||||
// -----------------------------------
|
||||
unsigned get_num_macros() const { return m_macro_manager.get_num_macros(); }
|
||||
unsigned get_first_macro_last_level() const { return m_macro_manager.get_first_macro_last_level(); }
|
||||
func_decl * get_macro_func_decl(unsigned i) const { return m_macro_manager.get_macro_func_decl(i); }
|
||||
func_decl * get_macro_interpretation(unsigned i, expr_ref & interp) const { return m_macro_manager.get_macro_interpretation(i, interp); }
|
||||
quantifier * get_macro_quantifier(func_decl * f) const { return m_macro_manager.get_macro_quantifier(f); }
|
||||
// auxiliary function used to create a logic context based on a model.
|
||||
void insert_macro(func_decl * f, quantifier * m, proof * pr) { m_macro_manager.insert(f, m, pr); }
|
||||
|
||||
// -----------------------------------
|
||||
//
|
||||
// Eliminated vars
|
||||
//
|
||||
// -----------------------------------
|
||||
ptr_vector<app>::const_iterator begin_subst_vars() const { return m_vars.begin(); }
|
||||
ptr_vector<app>::const_iterator end_subst_vars() const { return m_vars.end(); }
|
||||
ptr_vector<app>::const_iterator begin_subst_vars_last_level() const {
|
||||
unsigned sidx = m_scopes.empty() ? 0 : m_scopes.back().m_vars_lim;
|
||||
return m_vars.begin() + sidx;
|
||||
}
|
||||
expr * get_subst(app * var) { expr * def = 0; proof * pr; m_subst.get(var, def, pr); return def; }
|
||||
bool is_subst(app * var) const { return m_subst.contains(var); }
|
||||
void get_ordered_subst_vars(ptr_vector<app> & ordered_vars);
|
||||
};
|
||||
|
||||
#endif /* _ASSERTED_FORMULAS_H_ */
|
||||
|
430
lib/assertion_set.cpp
Normal file
430
lib/assertion_set.cpp
Normal file
|
@ -0,0 +1,430 @@
|
|||
/*++
|
||||
Copyright (c) 2011 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
assertion_set.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Assertion set.
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2011-04-20
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include"assertion_set.h"
|
||||
#include"cmd_context.h"
|
||||
#include"ast_ll_pp.h"
|
||||
#include"ast_smt2_pp.h"
|
||||
#include"for_each_expr.h"
|
||||
|
||||
void assertion_set::copy(assertion_set & target) const {
|
||||
if (this == &target)
|
||||
return;
|
||||
m().copy(m_forms, target.m_forms);
|
||||
m().copy(m_proofs, target.m_proofs);
|
||||
target.m_inconsistent = m_inconsistent;
|
||||
}
|
||||
|
||||
void assertion_set::push_back(expr * f, proof * pr) {
|
||||
if (m().is_true(f))
|
||||
return;
|
||||
if (m().is_false(f)) {
|
||||
m().del(m_forms);
|
||||
m().del(m_proofs);
|
||||
m_inconsistent = true;
|
||||
}
|
||||
else {
|
||||
SASSERT(!m_inconsistent);
|
||||
}
|
||||
m().push_back(m_forms, f);
|
||||
if (m().proofs_enabled())
|
||||
m().push_back(m_proofs, pr);
|
||||
}
|
||||
|
||||
void assertion_set::quick_process(bool save_first, expr * & f) {
|
||||
if (!m().is_and(f) && !(m().is_not(f) && m().is_or(to_app(f)->get_arg(0)))) {
|
||||
if (!save_first) {
|
||||
push_back(f, 0);
|
||||
}
|
||||
return;
|
||||
}
|
||||
typedef std::pair<expr *, bool> expr_pol;
|
||||
sbuffer<expr_pol, 64> todo;
|
||||
todo.push_back(expr_pol(f, true));
|
||||
while (!todo.empty()) {
|
||||
if (m_inconsistent)
|
||||
return;
|
||||
expr_pol p = todo.back();
|
||||
expr * curr = p.first;
|
||||
bool pol = p.second;
|
||||
todo.pop_back();
|
||||
if (pol && m().is_and(curr)) {
|
||||
app * t = to_app(curr);
|
||||
unsigned i = t->get_num_args();
|
||||
while (i > 0) {
|
||||
--i;
|
||||
todo.push_back(expr_pol(t->get_arg(i), true));
|
||||
}
|
||||
}
|
||||
else if (!pol && m().is_or(curr)) {
|
||||
app * t = to_app(curr);
|
||||
unsigned i = t->get_num_args();
|
||||
while (i > 0) {
|
||||
--i;
|
||||
todo.push_back(expr_pol(t->get_arg(i), false));
|
||||
}
|
||||
}
|
||||
else if (m().is_not(curr)) {
|
||||
todo.push_back(expr_pol(to_app(curr)->get_arg(0), !pol));
|
||||
}
|
||||
else {
|
||||
if (!pol)
|
||||
curr = m().mk_not(curr);
|
||||
if (save_first) {
|
||||
f = curr;
|
||||
save_first = false;
|
||||
}
|
||||
else {
|
||||
push_back(curr, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void assertion_set::process_and(bool save_first, app * f, proof * pr, expr_ref & out_f, proof_ref & out_pr) {
|
||||
unsigned num = f->get_num_args();
|
||||
for (unsigned i = 0; i < num; i++) {
|
||||
if (m_inconsistent)
|
||||
return;
|
||||
slow_process(save_first && i == 0, f->get_arg(i), m().mk_and_elim(pr, i), out_f, out_pr);
|
||||
}
|
||||
}
|
||||
|
||||
void assertion_set::process_not_or(bool save_first, app * f, proof * pr, expr_ref & out_f, proof_ref & out_pr) {
|
||||
unsigned num = f->get_num_args();
|
||||
for (unsigned i = 0; i < num; i++) {
|
||||
if (m_inconsistent)
|
||||
return;
|
||||
expr * child = f->get_arg(i);
|
||||
if (m().is_not(child)) {
|
||||
expr * not_child = to_app(child)->get_arg(0);
|
||||
slow_process(save_first && i == 0, not_child, m().mk_not_or_elim(pr, i), out_f, out_pr);
|
||||
}
|
||||
else {
|
||||
expr_ref not_child(m());
|
||||
not_child = m().mk_not(child);
|
||||
slow_process(save_first && i == 0, not_child, m().mk_not_or_elim(pr, i), out_f, out_pr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void assertion_set::slow_process(bool save_first, expr * f, proof * pr, expr_ref & out_f, proof_ref & out_pr) {
|
||||
if (m().is_and(f))
|
||||
process_and(save_first, to_app(f), pr, out_f, out_pr);
|
||||
else if (m().is_not(f) && m().is_or(to_app(f)->get_arg(0)))
|
||||
process_not_or(save_first, to_app(to_app(f)->get_arg(0)), pr, out_f, out_pr);
|
||||
else if (save_first) {
|
||||
out_f = f;
|
||||
out_pr = pr;
|
||||
}
|
||||
else {
|
||||
push_back(f, pr);
|
||||
}
|
||||
}
|
||||
|
||||
void assertion_set::slow_process(expr * f, proof * pr) {
|
||||
expr_ref out_f(m());
|
||||
proof_ref out_pr(m());
|
||||
slow_process(false, f, pr, out_f, out_pr);
|
||||
}
|
||||
|
||||
void assertion_set::assert_expr(expr * f, proof * pr) {
|
||||
SASSERT(m().proofs_enabled() == (pr != 0 && !m().is_undef_proof(pr)));
|
||||
if (m_inconsistent)
|
||||
return;
|
||||
if (m().proofs_enabled())
|
||||
slow_process(f, pr);
|
||||
else
|
||||
quick_process(false, f);
|
||||
}
|
||||
|
||||
void assertion_set::update(unsigned i, expr * f, proof * pr) {
|
||||
SASSERT(m().proofs_enabled() == (pr != 0 && !m().is_undef_proof(pr)));
|
||||
if (m_inconsistent)
|
||||
return;
|
||||
if (m().proofs_enabled()) {
|
||||
expr_ref out_f(m());
|
||||
proof_ref out_pr(m());
|
||||
slow_process(true, f, pr, out_f, out_pr);
|
||||
if (!m_inconsistent) {
|
||||
if (m().is_false(out_f)) {
|
||||
push_back(out_f, out_pr);
|
||||
}
|
||||
else {
|
||||
m().set(m_forms, i, out_f);
|
||||
m().set(m_proofs, i, out_pr);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
quick_process(true, f);
|
||||
if (!m_inconsistent) {
|
||||
if (m().is_false(f))
|
||||
push_back(f, 0);
|
||||
else
|
||||
m().set(m_forms, i, f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void assertion_set::reset() {
|
||||
m().del(m_forms);
|
||||
m().del(m_proofs);
|
||||
m_inconsistent = false;
|
||||
}
|
||||
|
||||
void assertion_set::display(cmd_context & ctx, std::ostream & out) const {
|
||||
out << "(assertion-set";
|
||||
unsigned sz = size();
|
||||
for (unsigned i = 0; i < sz; i++) {
|
||||
out << "\n ";
|
||||
ctx.display(out, form(i), 2);
|
||||
}
|
||||
out << ")" << std::endl;
|
||||
}
|
||||
|
||||
void assertion_set::display(cmd_context & ctx) const {
|
||||
display(ctx, ctx.regular_stream());
|
||||
}
|
||||
|
||||
void assertion_set::display(std::ostream & out) const {
|
||||
out << "(assertion-set";
|
||||
unsigned sz = size();
|
||||
for (unsigned i = 0; i < sz; i++) {
|
||||
out << "\n ";
|
||||
out << mk_ismt2_pp(form(i), m(), 2);
|
||||
}
|
||||
out << ")" << std::endl;
|
||||
}
|
||||
|
||||
void assertion_set::display_as_and(std::ostream & out) const {
|
||||
ptr_buffer<expr> args;
|
||||
unsigned sz = size();
|
||||
for (unsigned i = 0; i < sz; i++)
|
||||
args.push_back(form(i));
|
||||
expr_ref tmp(m());
|
||||
tmp = m().mk_and(args.size(), args.c_ptr());
|
||||
out << mk_ismt2_pp(tmp, m()) << "\n";
|
||||
}
|
||||
|
||||
void assertion_set::display_ll(std::ostream & out) const {
|
||||
unsigned sz = size();
|
||||
for (unsigned i = 0; i < sz; i++) {
|
||||
out << mk_ll_pp(form(i), m()) << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Assumes that the formula is already in CNF.
|
||||
*/
|
||||
void assertion_set::display_dimacs(std::ostream & out) const {
|
||||
obj_map<expr, unsigned> expr2var;
|
||||
unsigned num_vars = 0;
|
||||
unsigned num_cls = size();
|
||||
for (unsigned i = 0; i < num_cls; i++) {
|
||||
expr * f = form(i);
|
||||
unsigned num_lits;
|
||||
expr * const * lits;
|
||||
if (m().is_or(f)) {
|
||||
num_lits = to_app(f)->get_num_args();
|
||||
lits = to_app(f)->get_args();
|
||||
}
|
||||
else {
|
||||
num_lits = 1;
|
||||
lits = &f;
|
||||
}
|
||||
for (unsigned j = 0; j < num_lits; j++) {
|
||||
expr * l = lits[j];
|
||||
if (m().is_not(l))
|
||||
l = to_app(l)->get_arg(0);
|
||||
if (expr2var.contains(l))
|
||||
continue;
|
||||
num_vars++;
|
||||
expr2var.insert(l, num_vars);
|
||||
}
|
||||
}
|
||||
out << "p cnf " << num_vars << " " << num_cls << "\n";
|
||||
for (unsigned i = 0; i < num_cls; i++) {
|
||||
expr * f = form(i);
|
||||
unsigned num_lits;
|
||||
expr * const * lits;
|
||||
if (m().is_or(f)) {
|
||||
num_lits = to_app(f)->get_num_args();
|
||||
lits = to_app(f)->get_args();
|
||||
}
|
||||
else {
|
||||
num_lits = 1;
|
||||
lits = &f;
|
||||
}
|
||||
for (unsigned j = 0; j < num_lits; j++) {
|
||||
expr * l = lits[j];
|
||||
if (m().is_not(l)) {
|
||||
out << "-";
|
||||
l = to_app(l)->get_arg(0);
|
||||
}
|
||||
unsigned id = UINT_MAX;
|
||||
expr2var.find(l, id);
|
||||
SASSERT(id != UINT_MAX);
|
||||
out << id << " ";
|
||||
}
|
||||
out << "0\n";
|
||||
}
|
||||
}
|
||||
|
||||
unsigned assertion_set::num_exprs() const {
|
||||
expr_fast_mark1 visited;
|
||||
unsigned sz = size();
|
||||
unsigned r = 0;
|
||||
for (unsigned i = 0; i < sz; i++) {
|
||||
r += get_num_exprs(form(i), visited);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Eliminate true formulas.
|
||||
*/
|
||||
void assertion_set::elim_true() {
|
||||
unsigned sz = size();
|
||||
unsigned j = 0;
|
||||
for (unsigned i = 0; i < sz; i++) {
|
||||
expr * f = form(i);
|
||||
if (m().is_true(f))
|
||||
continue;
|
||||
if (i == j) {
|
||||
j++;
|
||||
continue;
|
||||
}
|
||||
m().set(m_forms, j, f);
|
||||
if (m().proofs_enabled())
|
||||
m().set(m_proofs, j, m().get(m_proofs, i));
|
||||
j++;
|
||||
}
|
||||
for (; j < sz; j++) {
|
||||
m().pop_back(m_forms);
|
||||
if (m().proofs_enabled())
|
||||
m().pop_back(m_proofs);
|
||||
}
|
||||
}
|
||||
|
||||
void assertion_set::elim_redundancies() {
|
||||
if (inconsistent())
|
||||
return;
|
||||
expr_ref_fast_mark1 neg_lits(m());
|
||||
expr_ref_fast_mark2 pos_lits(m());
|
||||
unsigned sz = size();
|
||||
unsigned j = 0;
|
||||
for (unsigned i = 0; i < sz; i++) {
|
||||
expr * f = form(i);
|
||||
if (m().is_true(f))
|
||||
continue;
|
||||
if (m().is_not(f)) {
|
||||
expr * atom = to_app(f)->get_arg(0);
|
||||
if (neg_lits.is_marked(atom))
|
||||
continue;
|
||||
if (pos_lits.is_marked(atom)) {
|
||||
proof * p = 0;
|
||||
if (m().proofs_enabled()) {
|
||||
proof * pr1 = 0;
|
||||
proof * pr2 = pr(i);
|
||||
for (unsigned j = 0; j < i; j++) {
|
||||
if (form(j) == atom) {
|
||||
pr1 = pr(j);
|
||||
break;
|
||||
}
|
||||
}
|
||||
SASSERT(pr1);
|
||||
proof * prs[2] = { pr1, pr2 };
|
||||
p = m().mk_unit_resolution(2, prs);
|
||||
}
|
||||
push_back(m().mk_false(), p);
|
||||
return;
|
||||
}
|
||||
neg_lits.mark(atom);
|
||||
}
|
||||
else {
|
||||
if (pos_lits.is_marked(f))
|
||||
continue;
|
||||
if (neg_lits.is_marked(f)) {
|
||||
proof * p = 0;
|
||||
if (m().proofs_enabled()) {
|
||||
proof * pr1 = 0;
|
||||
proof * pr2 = pr(i);
|
||||
for (unsigned j = 0; j < i; j++) {
|
||||
expr * curr = form(j);
|
||||
expr * atom;
|
||||
if (m().is_not(curr, atom) && atom == f) {
|
||||
pr1 = pr(j);
|
||||
break;
|
||||
}
|
||||
}
|
||||
SASSERT(pr1);
|
||||
proof * prs[2] = { pr1, pr2 };
|
||||
p = m().mk_unit_resolution(2, prs);
|
||||
}
|
||||
push_back(m().mk_false(), p);
|
||||
return;
|
||||
}
|
||||
pos_lits.mark(f);
|
||||
}
|
||||
if (i == j) {
|
||||
j++;
|
||||
continue;
|
||||
}
|
||||
m().set(m_forms, j, f);
|
||||
if (m().proofs_enabled())
|
||||
m().set(m_proofs, j, pr(i));
|
||||
j++;
|
||||
}
|
||||
|
||||
for (; j < sz; j++) {
|
||||
m().pop_back(m_forms);
|
||||
if (m().proofs_enabled())
|
||||
m().pop_back(m_proofs);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Assert expressions from ctx into t.
|
||||
*/
|
||||
void assert_exprs_from(cmd_context const & ctx, assertion_set & t) {
|
||||
ptr_vector<expr>::const_iterator it = ctx.begin_assertions();
|
||||
ptr_vector<expr>::const_iterator end = ctx.end_assertions();
|
||||
for (; it != end; ++it) {
|
||||
t.assert_expr(*it);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Translate the assertion set to a new one that uses a different ast_manager.
|
||||
*/
|
||||
assertion_set * assertion_set::translate(ast_translation & translator) const {
|
||||
ast_manager & m_to = translator.to();
|
||||
assertion_set * res = alloc(assertion_set, m_to);
|
||||
|
||||
unsigned sz = m().size(m_forms);
|
||||
for (unsigned i = 0; i < sz; i++) {
|
||||
res->m().push_back(res->m_forms, translator(m().get(m_forms, i)));
|
||||
if (m_to.proofs_enabled())
|
||||
res->m().push_back(res->m_proofs, translator(m().get(m_proofs, i)));
|
||||
}
|
||||
|
||||
res->m_inconsistent = m_inconsistent;
|
||||
|
||||
return res;
|
||||
}
|
98
lib/assertion_set.h
Normal file
98
lib/assertion_set.h
Normal file
|
@ -0,0 +1,98 @@
|
|||
/*++
|
||||
Copyright (c) 2011 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
assertion_set.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Assertion set.
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2011-04-20
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _ASSERTION_SET_H_
|
||||
#define _ASSERTION_SET_H_
|
||||
|
||||
#include"ast.h"
|
||||
#include"ast_translation.h"
|
||||
#include"for_each_expr.h"
|
||||
|
||||
class cmd_context;
|
||||
|
||||
class assertion_set {
|
||||
ast_manager & m_manager;
|
||||
bool m_inconsistent;
|
||||
expr_array m_forms;
|
||||
expr_array m_proofs;
|
||||
|
||||
void push_back(expr * f, proof * pr);
|
||||
void quick_process(bool save_first, expr * & f);
|
||||
void process_and(bool save_first, app * f, proof * pr, expr_ref & out_f, proof_ref & out_pr);
|
||||
void process_not_or(bool save_first, app * f, proof * pr, expr_ref & out_f, proof_ref & out_pr);
|
||||
void slow_process(bool save_first, expr * f, proof * pr, expr_ref & out_f, proof_ref & out_pr);
|
||||
void slow_process(expr * f, proof * pr);
|
||||
|
||||
public:
|
||||
assertion_set(ast_manager & m):m_manager(m), m_inconsistent(false) {}
|
||||
~assertion_set() { reset(); }
|
||||
|
||||
ast_manager & m() const { return m_manager; }
|
||||
|
||||
bool inconsistent() const { return m_inconsistent; }
|
||||
|
||||
void reset();
|
||||
|
||||
void copy(assertion_set & target) const;
|
||||
|
||||
void assert_expr(expr * f, proof * pr);
|
||||
|
||||
void assert_expr(expr * f) {
|
||||
assert_expr(f, m().mk_asserted(f));
|
||||
}
|
||||
|
||||
unsigned size() const { return m().size(m_forms); }
|
||||
|
||||
unsigned num_exprs() const;
|
||||
|
||||
expr * form(unsigned i) const { return m().get(m_forms, i); }
|
||||
|
||||
proof * pr(unsigned i) const { return m().proofs_enabled() ? static_cast<proof*>(m().get(m_proofs, i)) : 0; }
|
||||
|
||||
void update(unsigned i, expr * f, proof * pr = 0);
|
||||
|
||||
void elim_true();
|
||||
|
||||
void elim_redundancies();
|
||||
|
||||
void display(cmd_context & ctx, std::ostream & out) const;
|
||||
|
||||
void display(cmd_context & ctx) const;
|
||||
|
||||
void display(std::ostream & out) const;
|
||||
|
||||
void display_ll(std::ostream & out) const;
|
||||
|
||||
void display_as_and(std::ostream & out) const;
|
||||
|
||||
void display_dimacs(std::ostream & out) const;
|
||||
|
||||
assertion_set * translate(ast_translation & translator) const;
|
||||
};
|
||||
|
||||
void assert_exprs_from(cmd_context const & ctx, assertion_set & t);
|
||||
|
||||
template<typename ForEachProc>
|
||||
void for_each_expr_as(ForEachProc& proc, assertion_set const& s) {
|
||||
expr_mark visited;
|
||||
for (unsigned i = 0; i < s.size(); ++i) {
|
||||
for_each_expr(proc, visited, s.form(i));
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
78
lib/assertion_set.txt
Normal file
78
lib/assertion_set.txt
Normal file
|
@ -0,0 +1,78 @@
|
|||
|
||||
The assertion_set class is essentially a set of formulas.
|
||||
The assertion_set copy() method is constant time. They use persistent
|
||||
arrays for "sharing" common parts.
|
||||
The goal is to provide functors (strategies) that apply transformations to these sets.
|
||||
Examples of transformations are:
|
||||
- simplification
|
||||
- gaussian elimination
|
||||
- CNF, NNF, OCNF transformation
|
||||
- bit-blasting
|
||||
- abstraction
|
||||
- grobner basis computation
|
||||
- completion
|
||||
- term rewriting
|
||||
- bound propagation
|
||||
- contextal simplification
|
||||
- if-then-else lifting
|
||||
- quantifier elimination
|
||||
- etc
|
||||
|
||||
A functor/strategy is essentially updating an assertion set. It may
|
||||
also provide a model_converter to convert a model for the resultant
|
||||
assertion_set into a model for the original assertion_set. See
|
||||
gaussian_elim.cpp for an example of model_converter. A functor may
|
||||
return a vector of assertion sets. It may also return a
|
||||
proof_converter for converting proofs for the resultant assertion
|
||||
set(s) into a proof for the original assertion_set. The
|
||||
functor/strategy user is responsible for "plumbing" the
|
||||
model_converter(s) and proof_converter(s). In the future we may have
|
||||
tacticals for combining these functors/strategies. This is not needed
|
||||
now.
|
||||
|
||||
The idea is to provide assertion_set_solvers. They are essentially end-game
|
||||
strategies. The abstract API for them is defined at assertion_set_solver.h.
|
||||
Currently, the only assertion_set_solver is based on smt_context.h.
|
||||
The next one will be based on a pure SAT solver. I also have plans for
|
||||
one based on linear programming.
|
||||
|
||||
The main goals of the new design are:
|
||||
- increase modularity.
|
||||
- expose assertion_set abstraction to external users.
|
||||
- expose these functor/strategies to external users.
|
||||
- allow us to combine problem specific solvers in a modular way.
|
||||
- everything can be interrupted.
|
||||
- some actions may be resumed.
|
||||
- clean parallel_z3 implementation.
|
||||
- support non-satisfiability preserving transformations.
|
||||
the basic idea is:
|
||||
* if the transformation is an over-approximation,
|
||||
then the model_converter must throw an exception if it
|
||||
can't convert the model into a model for the original assertion_set.
|
||||
* if the transformation is an under-approximation,
|
||||
then the proof_converter must throw an exception if it
|
||||
can't convert the proof(s) into a proof for the original assertion_set.
|
||||
I don't expect us to provide extensive support for proofs.
|
||||
So, under-approximations will never really be used to show that
|
||||
an assertion_set is unsatisfiable.
|
||||
|
||||
Another goal is to a solver object that is essentially invoking an
|
||||
external solver (process). I expect the external solver (in most cases) to be
|
||||
Z3 itself. The main advantages are: the main process is safe from crashes,
|
||||
and we can even invoke solvers in remote machines.
|
||||
|
||||
The new functor/strategy design is not meant for incremental solving.
|
||||
We may still have solvers that are incremental such as smt_context.h.
|
||||
|
||||
Additional remarks:
|
||||
|
||||
Failures and interruptions are reported using exceptions.
|
||||
Each functor must provide a cancel() method that can be invoked to
|
||||
interrupt it. A resume() method is optional. It is a must have if the
|
||||
functor/strategy may be too time consuming. Each functor may have its
|
||||
own set of parameters. See rewriter_params.h for an example. The
|
||||
parameters may have options such as m_max_memory for blocking the
|
||||
executiong of the functor. Each functor should have a cleanup()
|
||||
method that must reclaim (almost) all memory consumed by the functor.
|
||||
|
||||
|
717
lib/assertion_set2sat.cpp
Normal file
717
lib/assertion_set2sat.cpp
Normal file
|
@ -0,0 +1,717 @@
|
|||
/*++
|
||||
Copyright (c) 2011 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
assertion_set2sat.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
"Compile" an assertion set into the SAT engine.
|
||||
Atoms are "abstracted" into boolean variables.
|
||||
The mapping between boolean variables and atoms
|
||||
can be used to convert back the state of the
|
||||
SAT engine into an assertion set.
|
||||
|
||||
The idea is to support scenarios such as:
|
||||
1) simplify, blast, convert into SAT, and solve
|
||||
2) convert into SAT, apply SAT for a while, learn new units, and translate back into an assertion set.
|
||||
3) convert into SAT, apply SAT preprocessor (failed literal propagation, resolution, etc) and translate back into an assertion set.
|
||||
4) Convert boolean structure into SAT, convert atoms into another engine, combine engines using lazy combination, solve.
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo (leonardo) 2011-05-22
|
||||
|
||||
Notes:
|
||||
|
||||
--*/
|
||||
#include"assertion_set2sat.h"
|
||||
#include"ast_smt2_pp.h"
|
||||
#include"ref_util.h"
|
||||
#include"cooperate.h"
|
||||
#include"filter_model_converter.h"
|
||||
#include"model_evaluator.h"
|
||||
#include"for_each_expr.h"
|
||||
#include"model_v2_pp.h"
|
||||
#include"assertion_set_util.h"
|
||||
|
||||
struct assertion_set2sat::imp {
|
||||
struct frame {
|
||||
app * m_t;
|
||||
unsigned m_root:1;
|
||||
unsigned m_sign:1;
|
||||
unsigned m_idx;
|
||||
frame(app * t, bool r, bool s, unsigned idx):
|
||||
m_t(t), m_root(r), m_sign(s), m_idx(idx) {}
|
||||
};
|
||||
ast_manager & m;
|
||||
svector<frame> m_frame_stack;
|
||||
svector<sat::literal> m_result_stack;
|
||||
obj_map<app, sat::literal> m_cache;
|
||||
obj_hashtable<expr> m_interface_vars;
|
||||
sat::solver & m_solver;
|
||||
atom2bool_var & m_map;
|
||||
sat::bool_var m_true;
|
||||
bool m_ite_extra;
|
||||
unsigned long long m_max_memory;
|
||||
volatile bool m_cancel;
|
||||
|
||||
imp(ast_manager & _m, params_ref const & p, sat::solver & s, atom2bool_var & map):
|
||||
m(_m),
|
||||
m_solver(s),
|
||||
m_map(map) {
|
||||
updt_params(p);
|
||||
m_cancel = false;
|
||||
m_true = sat::null_bool_var;
|
||||
}
|
||||
|
||||
void updt_params(params_ref const & p) {
|
||||
m_ite_extra = p.get_bool(":ite-extra", true);
|
||||
m_max_memory = megabytes_to_bytes(p.get_uint(":max-memory", UINT_MAX));
|
||||
}
|
||||
|
||||
void throw_op_not_handled() {
|
||||
throw assertion_set2sat_exception("operator not supported, apply simplifier before invoking translator");
|
||||
}
|
||||
|
||||
void mk_clause(sat::literal l) {
|
||||
TRACE("assertion_set2sat", tout << "mk_clause: " << l << "\n";);
|
||||
m_solver.mk_clause(1, &l);
|
||||
}
|
||||
|
||||
void mk_clause(sat::literal l1, sat::literal l2) {
|
||||
TRACE("assertion_set2sat", tout << "mk_clause: " << l1 << " " << l2 << "\n";);
|
||||
m_solver.mk_clause(l1, l2);
|
||||
}
|
||||
|
||||
void mk_clause(sat::literal l1, sat::literal l2, sat::literal l3) {
|
||||
TRACE("assertion_set2sat", tout << "mk_clause: " << l1 << " " << l2 << " " << l3 << "\n";);
|
||||
m_solver.mk_clause(l1, l2, l3);
|
||||
}
|
||||
|
||||
void mk_clause(unsigned num, sat::literal * lits) {
|
||||
TRACE("assertion_set2sat", tout << "mk_clause: "; for (unsigned i = 0; i < num; i++) tout << lits[i] << " "; tout << "\n";);
|
||||
m_solver.mk_clause(num, lits);
|
||||
}
|
||||
|
||||
sat::bool_var mk_true() {
|
||||
// create fake variable to represent true;
|
||||
if (m_true == sat::null_bool_var) {
|
||||
m_true = m_solver.mk_var();
|
||||
mk_clause(sat::literal(m_true, false)); // v is true
|
||||
}
|
||||
return m_true;
|
||||
}
|
||||
|
||||
void convert_atom(expr * t, bool root, bool sign) {
|
||||
SASSERT(m.is_bool(t));
|
||||
sat::literal l;
|
||||
sat::bool_var v = m_map.to_bool_var(t);
|
||||
if (v == sat::null_bool_var) {
|
||||
if (m.is_true(t)) {
|
||||
l = sat::literal(mk_true(), sign);
|
||||
}
|
||||
else if (m.is_false(t)) {
|
||||
l = sat::literal(mk_true(), !sign);
|
||||
}
|
||||
else {
|
||||
bool ext = !is_uninterp_const(t) || m_interface_vars.contains(t);
|
||||
sat::bool_var v = m_solver.mk_var(ext);
|
||||
m_map.insert(t, v);
|
||||
l = sat::literal(v, sign);
|
||||
TRACE("assertion_set2sat", tout << "new_var: " << v << "\n" << mk_ismt2_pp(t, m) << "\n";);
|
||||
}
|
||||
}
|
||||
else {
|
||||
SASSERT(v != sat::null_bool_var);
|
||||
l = sat::literal(v, sign);
|
||||
}
|
||||
SASSERT(l != sat::null_literal);
|
||||
if (root)
|
||||
mk_clause(l);
|
||||
else
|
||||
m_result_stack.push_back(l);
|
||||
}
|
||||
|
||||
bool process_cached(app * t, bool root, bool sign) {
|
||||
sat::literal l;
|
||||
if (m_cache.find(t, l)) {
|
||||
if (sign)
|
||||
l.neg();
|
||||
if (root)
|
||||
mk_clause(l);
|
||||
else
|
||||
m_result_stack.push_back(l);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool visit(expr * t, bool root, bool sign) {
|
||||
if (!is_app(t)) {
|
||||
convert_atom(t, root, sign);
|
||||
return true;
|
||||
}
|
||||
if (process_cached(to_app(t), root, sign))
|
||||
return true;
|
||||
if (to_app(t)->get_family_id() != m.get_basic_family_id()) {
|
||||
convert_atom(t, root, sign);
|
||||
return true;
|
||||
}
|
||||
switch (to_app(t)->get_decl_kind()) {
|
||||
case OP_NOT:
|
||||
case OP_OR:
|
||||
case OP_IFF:
|
||||
m_frame_stack.push_back(frame(to_app(t), root, sign, 0));
|
||||
return false;
|
||||
case OP_ITE:
|
||||
case OP_EQ:
|
||||
if (m.is_bool(to_app(t)->get_arg(1))) {
|
||||
m_frame_stack.push_back(frame(to_app(t), root, sign, 0));
|
||||
return false;
|
||||
}
|
||||
convert_atom(t, root, sign);
|
||||
return true;
|
||||
case OP_AND:
|
||||
case OP_XOR:
|
||||
case OP_IMPLIES:
|
||||
case OP_DISTINCT:
|
||||
TRACE("assertion_set2sat_not_handled", tout << mk_ismt2_pp(t, m) << "\n";);
|
||||
throw_op_not_handled();
|
||||
default:
|
||||
convert_atom(t, root, sign);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void convert_or(app * t, bool root, bool sign) {
|
||||
TRACE("assertion_set2sat", tout << "convert_or:\n" << mk_ismt2_pp(t, m) << "\n";);
|
||||
unsigned num = t->get_num_args();
|
||||
if (root) {
|
||||
SASSERT(num == m_result_stack.size());
|
||||
if (sign) {
|
||||
// this case should not really happen.
|
||||
for (unsigned i = 0; i < num; i++) {
|
||||
sat::literal l = m_result_stack[i];
|
||||
l.neg();
|
||||
mk_clause(l);
|
||||
}
|
||||
}
|
||||
else {
|
||||
mk_clause(m_result_stack.size(), m_result_stack.c_ptr());
|
||||
m_result_stack.reset();
|
||||
}
|
||||
}
|
||||
else {
|
||||
SASSERT(num <= m_result_stack.size());
|
||||
sat::bool_var k = m_solver.mk_var();
|
||||
sat::literal l(k, false);
|
||||
m_cache.insert(t, l);
|
||||
sat::literal * lits = m_result_stack.end() - num;
|
||||
for (unsigned i = 0; i < num; i++) {
|
||||
mk_clause(~lits[i], l);
|
||||
}
|
||||
m_result_stack.push_back(~l);
|
||||
lits = m_result_stack.end() - num - 1;
|
||||
// remark: mk_clause may perform destructive updated to lits.
|
||||
// I have to execute it after the binary mk_clause above.
|
||||
mk_clause(num+1, lits);
|
||||
unsigned old_sz = m_result_stack.size() - num - 1;
|
||||
m_result_stack.shrink(old_sz);
|
||||
if (sign)
|
||||
l.neg();
|
||||
m_result_stack.push_back(l);
|
||||
}
|
||||
}
|
||||
|
||||
void convert_ite(app * n, bool root, bool sign) {
|
||||
unsigned sz = m_result_stack.size();
|
||||
SASSERT(sz >= 3);
|
||||
sat::literal c = m_result_stack[sz-3];
|
||||
sat::literal t = m_result_stack[sz-2];
|
||||
sat::literal e = m_result_stack[sz-1];
|
||||
if (root) {
|
||||
SASSERT(sz == 3);
|
||||
if (sign) {
|
||||
mk_clause(~c, ~t);
|
||||
mk_clause(c, ~e);
|
||||
}
|
||||
else {
|
||||
mk_clause(~c, t);
|
||||
mk_clause(c, e);
|
||||
}
|
||||
m_result_stack.reset();
|
||||
}
|
||||
else {
|
||||
sat::bool_var k = m_solver.mk_var();
|
||||
sat::literal l(k, false);
|
||||
m_cache.insert(n, l);
|
||||
mk_clause(~l, ~c, t);
|
||||
mk_clause(~l, c, e);
|
||||
mk_clause(l, ~c, ~t);
|
||||
mk_clause(l, c, ~e);
|
||||
if (m_ite_extra) {
|
||||
mk_clause(~t, ~e, l);
|
||||
mk_clause(t, e, ~l);
|
||||
}
|
||||
m_result_stack.shrink(sz-3);
|
||||
if (sign)
|
||||
l.neg();
|
||||
m_result_stack.push_back(l);
|
||||
}
|
||||
}
|
||||
|
||||
void convert_iff(app * t, bool root, bool sign) {
|
||||
TRACE("assertion_set2sat", tout << "convert_iff " << root << " " << sign << "\n" << mk_ismt2_pp(t, m) << "\n";);
|
||||
unsigned sz = m_result_stack.size();
|
||||
SASSERT(sz >= 2);
|
||||
sat::literal l1 = m_result_stack[sz-1];
|
||||
sat::literal l2 = m_result_stack[sz-2];
|
||||
if (root) {
|
||||
SASSERT(sz == 2);
|
||||
if (sign) {
|
||||
mk_clause(l1, l2);
|
||||
mk_clause(~l1, ~l2);
|
||||
}
|
||||
else {
|
||||
mk_clause(l1, ~l2);
|
||||
mk_clause(~l1, l2);
|
||||
}
|
||||
m_result_stack.reset();
|
||||
}
|
||||
else {
|
||||
sat::bool_var k = m_solver.mk_var();
|
||||
sat::literal l(k, false);
|
||||
m_cache.insert(t, l);
|
||||
mk_clause(~l, l1, ~l2);
|
||||
mk_clause(~l, ~l1, l2);
|
||||
mk_clause(l, l1, l2);
|
||||
mk_clause(l, ~l1, ~l2);
|
||||
m_result_stack.shrink(sz-2);
|
||||
if (sign)
|
||||
l.neg();
|
||||
m_result_stack.push_back(l);
|
||||
}
|
||||
}
|
||||
|
||||
void convert(app * t, bool root, bool sign) {
|
||||
SASSERT(t->get_family_id() == m.get_basic_family_id());
|
||||
switch (to_app(t)->get_decl_kind()) {
|
||||
case OP_OR:
|
||||
convert_or(t, root, sign);
|
||||
break;
|
||||
case OP_ITE:
|
||||
convert_ite(t, root, sign);
|
||||
break;
|
||||
case OP_IFF:
|
||||
case OP_EQ:
|
||||
convert_iff(t, root, sign);
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
void process(expr * n) {
|
||||
TRACE("assertion_set2sat", tout << "converting: " << mk_ismt2_pp(n, m) << "\n";);
|
||||
if (visit(n, true, false)) {
|
||||
SASSERT(m_result_stack.empty());
|
||||
return;
|
||||
}
|
||||
while (!m_frame_stack.empty()) {
|
||||
loop:
|
||||
cooperate("assertion_set2sat");
|
||||
if (m_cancel)
|
||||
throw assertion_set2sat_exception(STE_CANCELED_MSG);
|
||||
if (memory::get_allocation_size() > m_max_memory)
|
||||
throw assertion_set2sat_exception(STE_MAX_MEMORY_MSG);
|
||||
frame & fr = m_frame_stack.back();
|
||||
app * t = fr.m_t;
|
||||
bool root = fr.m_root;
|
||||
bool sign = fr.m_sign;
|
||||
TRACE("assertion_set2sat_bug", tout << "result stack\n";
|
||||
tout << mk_ismt2_pp(t, m) << " root: " << root << " sign: " << sign << "\n";
|
||||
for (unsigned i = 0; i < m_result_stack.size(); i++) tout << m_result_stack[i] << " ";
|
||||
tout << "\n";);
|
||||
if (fr.m_idx == 0 && process_cached(t, root, sign)) {
|
||||
m_frame_stack.pop_back();
|
||||
continue;
|
||||
}
|
||||
if (m.is_not(t)) {
|
||||
m_frame_stack.pop_back();
|
||||
visit(t->get_arg(0), root, !sign);
|
||||
continue;
|
||||
}
|
||||
unsigned num = t->get_num_args();
|
||||
while (fr.m_idx < num) {
|
||||
expr * arg = t->get_arg(fr.m_idx);
|
||||
fr.m_idx++;
|
||||
if (!visit(arg, false, false))
|
||||
goto loop;
|
||||
}
|
||||
TRACE("assertion_set2sat_bug", tout << "converting\n";
|
||||
tout << mk_ismt2_pp(t, m) << " root: " << root << " sign: " << sign << "\n";
|
||||
for (unsigned i = 0; i < m_result_stack.size(); i++) tout << m_result_stack[i] << " ";
|
||||
tout << "\n";);
|
||||
convert(t, root, sign);
|
||||
m_frame_stack.pop_back();
|
||||
}
|
||||
SASSERT(m_result_stack.empty());
|
||||
}
|
||||
|
||||
|
||||
void operator()(assertion_set const & s) {
|
||||
m_interface_vars.reset();
|
||||
collect_boolean_interface(s, m_interface_vars);
|
||||
|
||||
unsigned size = s.size();
|
||||
for (unsigned idx = 0; idx < size; idx++) {
|
||||
expr * f = s.form(idx);
|
||||
process(f);
|
||||
}
|
||||
}
|
||||
|
||||
void operator()(unsigned sz, expr * const * fs) {
|
||||
m_interface_vars.reset();
|
||||
collect_boolean_interface(m, sz, fs, m_interface_vars);
|
||||
|
||||
for (unsigned i = 0; i < sz; i++)
|
||||
process(fs[i]);
|
||||
}
|
||||
|
||||
void set_cancel(bool f) { m_cancel = f; }
|
||||
};
|
||||
|
||||
struct unsupported_bool_proc {
|
||||
struct found {};
|
||||
ast_manager & m;
|
||||
unsupported_bool_proc(ast_manager & _m):m(_m) {}
|
||||
void operator()(var *) {}
|
||||
void operator()(quantifier *) {}
|
||||
void operator()(app * n) {
|
||||
if (n->get_family_id() == m.get_basic_family_id()) {
|
||||
switch (n->get_decl_kind()) {
|
||||
case OP_AND:
|
||||
case OP_XOR:
|
||||
case OP_IMPLIES:
|
||||
case OP_DISTINCT:
|
||||
throw found();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
\brief Return true if s contains an unsupported Boolean operator.
|
||||
assertion_set_rewriter (with the following configuration) can be used to
|
||||
eliminate unsupported operators.
|
||||
:elim-and true
|
||||
:blast-distinct true
|
||||
*/
|
||||
bool assertion_set2sat::has_unsupported_bool(assertion_set const & s) {
|
||||
return test<unsupported_bool_proc>(s);
|
||||
}
|
||||
|
||||
assertion_set2sat::assertion_set2sat():m_imp(0) {
|
||||
}
|
||||
|
||||
void assertion_set2sat::collect_param_descrs(param_descrs & r) {
|
||||
insert_max_memory(r);
|
||||
r.insert(":ite-extra", CPK_BOOL, "(default: true) add redundant clauses (that improve unit propagation) when encoding if-then-else formulas");
|
||||
}
|
||||
|
||||
struct assertion_set2sat::scoped_set_imp {
|
||||
assertion_set2sat * m_owner;
|
||||
scoped_set_imp(assertion_set2sat * o, assertion_set2sat::imp * i):m_owner(o) {
|
||||
#pragma omp critical (assertion_set2sat)
|
||||
{
|
||||
m_owner->m_imp = i;
|
||||
}
|
||||
}
|
||||
~scoped_set_imp() {
|
||||
#pragma omp critical (assertion_set2sat)
|
||||
{
|
||||
m_owner->m_imp = 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void assertion_set2sat::operator()(assertion_set const & s, params_ref const & p, sat::solver & t, atom2bool_var & m) {
|
||||
imp proc(s.m(), p, t, m);
|
||||
scoped_set_imp set(this, &proc);
|
||||
proc(s);
|
||||
}
|
||||
|
||||
void assertion_set2sat::operator()(ast_manager & mng, unsigned num, expr * const * fs, params_ref const & p, sat::solver & t, atom2bool_var & m) {
|
||||
imp proc(mng, p, t, m);
|
||||
scoped_set_imp set(this, &proc);
|
||||
proc(num, fs);
|
||||
}
|
||||
|
||||
void assertion_set2sat::set_cancel(bool f) {
|
||||
#pragma omp critical (assertion_set2sat)
|
||||
{
|
||||
if (m_imp)
|
||||
m_imp->set_cancel(f);
|
||||
}
|
||||
}
|
||||
|
||||
class sat_model_converter : public model_converter {
|
||||
sat::model_converter m_mc;
|
||||
// TODO: the following mapping is storing a lot of useless information, and may be a performance bottleneck.
|
||||
// We need to save only the expressions associated with variables that occur in m_mc.
|
||||
// This information may be stored as a vector of pairs.
|
||||
// The mapping is only created during the model conversion.
|
||||
expr_ref_vector m_var2expr;
|
||||
ref<filter_model_converter> m_fmc; // filter for eliminating fresh variables introduced in the assertion-set --> sat conversion
|
||||
|
||||
sat_model_converter(ast_manager & m):
|
||||
m_var2expr(m) {
|
||||
}
|
||||
|
||||
public:
|
||||
sat_model_converter(ast_manager & m, sat::solver const & s):m_var2expr(m) {
|
||||
m_mc.copy(s.get_model_converter());
|
||||
m_fmc = alloc(filter_model_converter, m);
|
||||
}
|
||||
|
||||
ast_manager & m() { return m_var2expr.get_manager(); }
|
||||
|
||||
void insert(expr * atom, bool aux) {
|
||||
m_var2expr.push_back(atom);
|
||||
if (aux) {
|
||||
SASSERT(is_uninterp_const(atom));
|
||||
SASSERT(m().is_bool(atom));
|
||||
m_fmc->insert(to_app(atom)->get_decl());
|
||||
}
|
||||
}
|
||||
|
||||
virtual void operator()(model_ref & md) {
|
||||
TRACE("sat_mc", tout << "before sat_mc\n"; model_v2_pp(tout, *md); display(tout););
|
||||
// REMARK: potential problem
|
||||
// model_evaluator can't evaluate quantifiers. Then,
|
||||
// an eliminated variable that depends on a quantified expression can't be recovered.
|
||||
// A similar problem also affects any model_converter that uses elim_var_model_converter.
|
||||
//
|
||||
// Possible solution:
|
||||
// model_converters reject any variable elimination that depends on a quantified expression.
|
||||
|
||||
model_evaluator ev(*md);
|
||||
ev.set_model_completion(false);
|
||||
|
||||
// create a SAT model using md
|
||||
sat::model sat_md;
|
||||
unsigned sz = m_var2expr.size();
|
||||
expr_ref val(m());
|
||||
for (sat::bool_var v = 0; v < sz; v++) {
|
||||
expr * atom = m_var2expr.get(v);
|
||||
ev(atom, val);
|
||||
if (m().is_true(val))
|
||||
sat_md.push_back(l_true);
|
||||
else if (m().is_false(val))
|
||||
sat_md.push_back(l_false);
|
||||
else
|
||||
sat_md.push_back(l_undef);
|
||||
}
|
||||
|
||||
// apply SAT model converter
|
||||
m_mc(sat_md);
|
||||
|
||||
// register value of non-auxiliary boolean variables back into md
|
||||
sz = m_var2expr.size();
|
||||
for (sat::bool_var v = 0; v < sz; v++) {
|
||||
expr * atom = m_var2expr.get(v);
|
||||
if (is_uninterp_const(atom)) {
|
||||
func_decl * d = to_app(atom)->get_decl();
|
||||
lbool new_val = sat_md[v];
|
||||
if (new_val == l_true)
|
||||
md->register_decl(d, m().mk_true());
|
||||
else if (new_val == l_false)
|
||||
md->register_decl(d, m().mk_false());
|
||||
}
|
||||
}
|
||||
|
||||
// apply filter model converter
|
||||
(*m_fmc)(md);
|
||||
TRACE("sat_mc", tout << "after sat_mc\n"; model_v2_pp(tout, *md););
|
||||
}
|
||||
|
||||
virtual model_converter * translate(ast_translation & translator) {
|
||||
sat_model_converter * res = alloc(sat_model_converter, translator.to());
|
||||
res->m_fmc = static_cast<filter_model_converter*>(m_fmc->translate(translator));
|
||||
unsigned sz = m_var2expr.size();
|
||||
for (unsigned i = 0; i < sz; i++)
|
||||
res->m_var2expr.push_back(translator(m_var2expr.get(i)));
|
||||
return res;
|
||||
}
|
||||
|
||||
void display(std::ostream & out) {
|
||||
out << "(sat-model-converter\n";
|
||||
m_mc.display(out);
|
||||
sat::bool_var_set vars;
|
||||
m_mc.collect_vars(vars);
|
||||
out << "(atoms";
|
||||
unsigned sz = m_var2expr.size();
|
||||
for (unsigned i = 0; i < sz; i++) {
|
||||
if (vars.contains(i)) {
|
||||
out << "\n (" << i << "\n " << mk_ismt2_pp(m_var2expr.get(i), m(), 2) << ")";
|
||||
}
|
||||
}
|
||||
out << ")\n";
|
||||
m_fmc->display(out);
|
||||
out << ")\n";
|
||||
}
|
||||
};
|
||||
|
||||
struct sat2assertion_set::imp {
|
||||
ast_manager & m;
|
||||
expr_ref_vector m_lit2expr;
|
||||
unsigned long long m_max_memory;
|
||||
bool m_learned;
|
||||
bool m_produce_models;
|
||||
volatile bool m_cancel;
|
||||
|
||||
imp(ast_manager & _m, params_ref const & p):m(_m), m_lit2expr(m), m_cancel(false) {
|
||||
updt_params(p);
|
||||
}
|
||||
|
||||
void updt_params(params_ref const & p) {
|
||||
m_produce_models = p.get_bool(":produce-models", false);
|
||||
m_learned = p.get_bool(":learned", false);
|
||||
m_max_memory = megabytes_to_bytes(p.get_uint(":max-memory", UINT_MAX));
|
||||
}
|
||||
|
||||
void checkpoint() {
|
||||
if (m_cancel)
|
||||
throw sat2assertion_set_exception(STE_CANCELED_MSG);
|
||||
if (memory::get_allocation_size() > m_max_memory)
|
||||
throw sat2assertion_set_exception(STE_MAX_MEMORY_MSG);
|
||||
}
|
||||
|
||||
void init_lit2expr(sat::solver const & s, atom2bool_var const & map, model_converter_ref & mc) {
|
||||
ref<sat_model_converter> _mc;
|
||||
if (m_produce_models) {
|
||||
_mc = alloc(sat_model_converter, m, s);
|
||||
}
|
||||
unsigned num_vars = s.num_vars();
|
||||
m_lit2expr.resize(num_vars * 2);
|
||||
map.mk_inv(m_lit2expr);
|
||||
sort * b = m.mk_bool_sort();
|
||||
for (sat::bool_var v = 0; v < num_vars; v++) {
|
||||
checkpoint();
|
||||
sat::literal l(v, false);
|
||||
if (m_lit2expr.get(l.index()) == 0) {
|
||||
SASSERT(m_lit2expr.get((~l).index()) == 0);
|
||||
app * aux = m.mk_fresh_const(0, b);
|
||||
if (_mc)
|
||||
_mc->insert(aux, true);
|
||||
m_lit2expr.set(l.index(), aux);
|
||||
m_lit2expr.set((~l).index(), m.mk_not(aux));
|
||||
}
|
||||
else {
|
||||
if (_mc)
|
||||
_mc->insert(m_lit2expr.get(l.index()), false);
|
||||
SASSERT(m_lit2expr.get((~l).index()) != 0);
|
||||
}
|
||||
}
|
||||
mc = _mc.get();
|
||||
}
|
||||
|
||||
expr * lit2expr(sat::literal l) {
|
||||
return m_lit2expr.get(l.index());
|
||||
}
|
||||
|
||||
void assert_clauses(sat::clause * const * begin, sat::clause * const * end, assertion_set & r) {
|
||||
ptr_buffer<expr> lits;
|
||||
for (sat::clause * const * it = begin; it != end; it++) {
|
||||
checkpoint();
|
||||
lits.reset();
|
||||
sat::clause const & c = *(*it);
|
||||
unsigned sz = c.size();
|
||||
for (unsigned i = 0; i < sz; i++) {
|
||||
lits.push_back(lit2expr(c[i]));
|
||||
}
|
||||
r.assert_expr(m.mk_or(lits.size(), lits.c_ptr()));
|
||||
}
|
||||
}
|
||||
|
||||
void operator()(sat::solver const & s, atom2bool_var const & map, assertion_set & r, model_converter_ref & mc) {
|
||||
if (s.inconsistent()) {
|
||||
r.assert_expr(m.mk_false());
|
||||
return;
|
||||
}
|
||||
init_lit2expr(s, map, mc);
|
||||
// collect units
|
||||
unsigned num_vars = s.num_vars();
|
||||
for (sat::bool_var v = 0; v < num_vars; v++) {
|
||||
checkpoint();
|
||||
switch (s.value(v)) {
|
||||
case l_true:
|
||||
r.assert_expr(lit2expr(sat::literal(v, false)));
|
||||
break;
|
||||
case l_false:
|
||||
r.assert_expr(lit2expr(sat::literal(v, true)));
|
||||
break;
|
||||
case l_undef:
|
||||
break;
|
||||
}
|
||||
}
|
||||
// collect binary clauses
|
||||
svector<sat::solver::bin_clause> bin_clauses;
|
||||
s.collect_bin_clauses(bin_clauses, m_learned);
|
||||
svector<sat::solver::bin_clause>::iterator it = bin_clauses.begin();
|
||||
svector<sat::solver::bin_clause>::iterator end = bin_clauses.end();
|
||||
for (; it != end; ++it) {
|
||||
checkpoint();
|
||||
r.assert_expr(m.mk_or(lit2expr(it->first), lit2expr(it->second)));
|
||||
}
|
||||
// collect clauses
|
||||
assert_clauses(s.begin_clauses(), s.end_clauses(), r);
|
||||
if (m_learned)
|
||||
assert_clauses(s.begin_learned(), s.end_learned(), r);
|
||||
}
|
||||
|
||||
void set_cancel(bool f) { m_cancel = f; }
|
||||
};
|
||||
|
||||
sat2assertion_set::sat2assertion_set():m_imp(0) {
|
||||
}
|
||||
|
||||
void sat2assertion_set::collect_param_descrs(param_descrs & r) {
|
||||
insert_max_memory(r);
|
||||
r.insert(":learned", CPK_BOOL, "(default: false) collect also learned clauses.");
|
||||
}
|
||||
|
||||
struct sat2assertion_set::scoped_set_imp {
|
||||
sat2assertion_set * m_owner;
|
||||
scoped_set_imp(sat2assertion_set * o, sat2assertion_set::imp * i):m_owner(o) {
|
||||
#pragma omp critical (sat2assertion_set)
|
||||
{
|
||||
m_owner->m_imp = i;
|
||||
}
|
||||
}
|
||||
~scoped_set_imp() {
|
||||
#pragma omp critical (sat2assertion_set)
|
||||
{
|
||||
m_owner->m_imp = 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void sat2assertion_set::operator()(sat::solver const & t, atom2bool_var const & m, params_ref const & p,
|
||||
assertion_set & s, model_converter_ref & mc) {
|
||||
imp proc(s.m(), p);
|
||||
scoped_set_imp set(this, &proc);
|
||||
proc(t, m, s, mc);
|
||||
}
|
||||
|
||||
void sat2assertion_set::set_cancel(bool f) {
|
||||
#pragma omp critical (sat2assertion_set)
|
||||
{
|
||||
if (m_imp)
|
||||
m_imp->set_cancel(f);
|
||||
}
|
||||
}
|
95
lib/assertion_set2sat.h
Normal file
95
lib/assertion_set2sat.h
Normal file
|
@ -0,0 +1,95 @@
|
|||
/*++
|
||||
Copyright (c) 2011 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
assertion_set2sat.h
|
||||
|
||||
Abstract:
|
||||
|
||||
"Compile" an assertion set into the SAT engine.
|
||||
Atoms are "abstracted" into boolean variables.
|
||||
The mapping between boolean variables and atoms
|
||||
can be used to convert back the state of the
|
||||
SAT engine into an assertion set.
|
||||
|
||||
The idea is to support scenarios such as:
|
||||
1) simplify, blast, convert into SAT, and solve
|
||||
2) convert into SAT, apply SAT for a while, learn new units, and translate back into an assertion set.
|
||||
3) convert into SAT, apply SAT preprocessor (failed literal propagation, resolution, etc) and translate back into an assertion set.
|
||||
4) Convert boolean structure into SAT, convert atoms into another engine, combine engines using lazy combination, solve.
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo (leonardo) 2011-05-22
|
||||
|
||||
Notes:
|
||||
|
||||
--*/
|
||||
#ifndef _ASSERTION_SET2SAT_H_
|
||||
#define _ASSERTION_SET2SAT_H_
|
||||
|
||||
#include"assertion_set.h"
|
||||
#include"sat_solver.h"
|
||||
#include"strategy_exception.h"
|
||||
#include"model_converter.h"
|
||||
#include"atom2bool_var.h"
|
||||
|
||||
MK_ST_EXCEPTION(assertion_set2sat_exception);
|
||||
|
||||
class assertion_set2sat {
|
||||
struct imp;
|
||||
imp * m_imp;
|
||||
struct scoped_set_imp;
|
||||
public:
|
||||
assertion_set2sat();
|
||||
|
||||
static void collect_param_descrs(param_descrs & r);
|
||||
|
||||
static bool has_unsupported_bool(assertion_set const & s);
|
||||
|
||||
/**
|
||||
\brief "Compile" the assertion set into the given sat solver.
|
||||
Store a mapping from atoms to boolean variables into m.
|
||||
|
||||
\remark m doesn't need to be empty. the definitions there are
|
||||
reused.
|
||||
*/
|
||||
void operator()(assertion_set const & s, params_ref const & p, sat::solver & t, atom2bool_var & m);
|
||||
|
||||
/**
|
||||
\brief "Compile" the formulas fs into the given sat solver.
|
||||
Store a mapping from atoms to boolean variables into m.
|
||||
|
||||
\remark m doesn't need to be empty. the definitions there are
|
||||
reused.
|
||||
*/
|
||||
void operator()(ast_manager & mng, unsigned num, expr * const * fs, params_ref const & p, sat::solver & t, atom2bool_var & m);
|
||||
|
||||
void operator()(ast_manager & mng, expr * f, params_ref const & p, sat::solver & t, atom2bool_var & m) { operator()(mng, 1, &f, p, t, m); }
|
||||
|
||||
void set_cancel(bool f);
|
||||
};
|
||||
|
||||
MK_ST_EXCEPTION(sat2assertion_set_exception);
|
||||
|
||||
class sat2assertion_set {
|
||||
struct imp;
|
||||
imp * m_imp;
|
||||
struct scoped_set_imp;
|
||||
public:
|
||||
sat2assertion_set();
|
||||
|
||||
static void collect_param_descrs(param_descrs & r);
|
||||
|
||||
/**
|
||||
\brief Translate the state of the SAT engine back into an assertion set.
|
||||
The SAT solver may use variables that are not in \c m. The translator
|
||||
creates fresh boolean AST variables for them. They are stored in fvars.
|
||||
*/
|
||||
void operator()(sat::solver const & t, atom2bool_var const & m, params_ref const & p, assertion_set & s, model_converter_ref & mc);
|
||||
|
||||
void set_cancel(bool f);
|
||||
};
|
||||
|
||||
#endif
|
122
lib/assertion_set_rewriter.cpp
Normal file
122
lib/assertion_set_rewriter.cpp
Normal file
|
@ -0,0 +1,122 @@
|
|||
/*++
|
||||
Copyright (c) 2011 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
assertion_set_rewriter.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Apply rewriting rules in an assertion set.
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo (leonardo) 2011-04-27
|
||||
|
||||
Notes:
|
||||
|
||||
--*/
|
||||
#include"assertion_set_rewriter.h"
|
||||
#include"th_rewriter.h"
|
||||
#include"ast_smt2_pp.h"
|
||||
#include"assertion_set_util.h"
|
||||
|
||||
struct assertion_set_rewriter::imp {
|
||||
ast_manager & m_manager;
|
||||
th_rewriter m_r;
|
||||
unsigned m_num_steps;
|
||||
|
||||
imp(ast_manager & m, params_ref const & p):
|
||||
m_manager(m),
|
||||
m_r(m, p),
|
||||
m_num_steps(0) {
|
||||
}
|
||||
|
||||
ast_manager & m() const { return m_manager; }
|
||||
|
||||
void set_cancel(bool f) {
|
||||
m_r.set_cancel(f);
|
||||
}
|
||||
|
||||
void reset() {
|
||||
m_r.reset();
|
||||
m_num_steps = 0;
|
||||
}
|
||||
|
||||
void operator()(assertion_set & s) {
|
||||
SASSERT(is_well_sorted(s));
|
||||
as_st_report report("simplifier", s);
|
||||
TRACE("before_simplifier", s.display(tout););
|
||||
m_num_steps = 0;
|
||||
if (s.inconsistent())
|
||||
return;
|
||||
expr_ref new_curr(m());
|
||||
proof_ref new_pr(m());
|
||||
unsigned size = s.size();
|
||||
for (unsigned idx = 0; idx < size; idx++) {
|
||||
if (s.inconsistent())
|
||||
break;
|
||||
expr * curr = s.form(idx);
|
||||
m_r(curr, new_curr, new_pr);
|
||||
m_num_steps += m_r.get_num_steps();
|
||||
if (m().proofs_enabled()) {
|
||||
proof * pr = s.pr(idx);
|
||||
new_pr = m().mk_modus_ponens(pr, new_pr);
|
||||
}
|
||||
s.update(idx, new_curr, new_pr);
|
||||
}
|
||||
TRACE("after_simplifier_bug", s.display(tout););
|
||||
s.elim_redundancies();
|
||||
TRACE("after_simplifier", s.display(tout););
|
||||
SASSERT(is_well_sorted(s));
|
||||
}
|
||||
|
||||
unsigned get_num_steps() const { return m_num_steps; }
|
||||
};
|
||||
|
||||
assertion_set_rewriter::assertion_set_rewriter(ast_manager & m, params_ref const & p):
|
||||
m_params(p) {
|
||||
m_imp = alloc(imp, m, p);
|
||||
}
|
||||
|
||||
assertion_set_rewriter::~assertion_set_rewriter() {
|
||||
dealloc(m_imp);
|
||||
}
|
||||
|
||||
void assertion_set_rewriter::updt_params(params_ref const & p) {
|
||||
m_params = p;
|
||||
m_imp->m_r.updt_params(p);
|
||||
}
|
||||
|
||||
void assertion_set_rewriter::get_param_descrs(param_descrs & r) {
|
||||
th_rewriter::get_param_descrs(r);
|
||||
}
|
||||
|
||||
void assertion_set_rewriter::operator()(assertion_set & s) {
|
||||
m_imp->operator()(s);
|
||||
}
|
||||
|
||||
void assertion_set_rewriter::set_cancel(bool f) {
|
||||
if (m_imp)
|
||||
m_imp->set_cancel(f);
|
||||
}
|
||||
|
||||
void assertion_set_rewriter::cleanup() {
|
||||
ast_manager & m = m_imp->m();
|
||||
imp * d = m_imp;
|
||||
#pragma omp critical (as_st_cancel)
|
||||
{
|
||||
m_imp = 0;
|
||||
}
|
||||
dealloc(d);
|
||||
d = alloc(imp, m, m_params);
|
||||
#pragma omp critical (as_st_cancel)
|
||||
{
|
||||
m_imp = d;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned assertion_set_rewriter::get_num_steps() const {
|
||||
return m_imp->get_num_steps();
|
||||
}
|
||||
|
56
lib/assertion_set_rewriter.h
Normal file
56
lib/assertion_set_rewriter.h
Normal file
|
@ -0,0 +1,56 @@
|
|||
/*++
|
||||
Copyright (c) 2011 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
assertion_set_rewriter.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Apply rewriting rules in an assertion set.
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo (leonardo) 2011-04-22
|
||||
|
||||
Notes:
|
||||
|
||||
--*/
|
||||
#ifndef _ASSERTION_SET_REWRITER_H_
|
||||
#define _ASSERTION_SET_REWRITER_H_
|
||||
|
||||
#include"assertion_set_strategy.h"
|
||||
|
||||
class assertion_set_rewriter : public assertion_set_strategy {
|
||||
struct imp;
|
||||
imp * m_imp;
|
||||
params_ref m_params;
|
||||
public:
|
||||
assertion_set_rewriter(ast_manager & m, params_ref const & ref = params_ref());
|
||||
virtual ~assertion_set_rewriter();
|
||||
|
||||
virtual void updt_params(params_ref const & p);
|
||||
static void get_param_descrs(param_descrs & r);
|
||||
virtual void collect_param_descrs(param_descrs & r) { get_param_descrs(r); }
|
||||
|
||||
/**
|
||||
\brief Apply rewriting/simplification rules on the assertion set \c s.
|
||||
*/
|
||||
void operator()(assertion_set & s);
|
||||
|
||||
virtual void operator()(assertion_set & s, model_converter_ref & mc) {
|
||||
operator()(s);
|
||||
mc = 0;
|
||||
}
|
||||
|
||||
virtual void cleanup();
|
||||
|
||||
unsigned get_num_steps() const;
|
||||
virtual void set_cancel(bool f);
|
||||
};
|
||||
|
||||
inline as_st * mk_simplifier(ast_manager & m, params_ref const & p = params_ref()) {
|
||||
return clean(alloc(assertion_set_rewriter, m, p));
|
||||
}
|
||||
|
||||
#endif
|
1414
lib/assertion_set_strategy.cpp
Normal file
1414
lib/assertion_set_strategy.cpp
Normal file
File diff suppressed because it is too large
Load diff
228
lib/assertion_set_strategy.h
Normal file
228
lib/assertion_set_strategy.h
Normal file
|
@ -0,0 +1,228 @@
|
|||
/*++
|
||||
Copyright (c) 2011 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
assertion_set_strategy.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Abstract strategy for assertion sets, and simple combinators.
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo (leonardo) 2011-05-17
|
||||
|
||||
Notes:
|
||||
|
||||
--*/
|
||||
#ifndef _AS_STRATEGY_H_
|
||||
#define _AS_STRATEGY_H_
|
||||
|
||||
#include"params.h"
|
||||
#include"assertion_set.h"
|
||||
#include"model_converter.h"
|
||||
#include"statistics.h"
|
||||
#include"strategy_exception.h"
|
||||
#include"lbool.h"
|
||||
#include"assertion_set_util.h"
|
||||
|
||||
struct front_end_params;
|
||||
|
||||
class progress_callback;
|
||||
|
||||
// minimum verbosity level for strategies
|
||||
#define ST_VERBOSITY_LVL 10
|
||||
|
||||
class as_st_report {
|
||||
struct imp;
|
||||
imp * m_imp;
|
||||
public:
|
||||
as_st_report(char const * id, assertion_set & s);
|
||||
~as_st_report();
|
||||
};
|
||||
|
||||
void report_st_progress(char const * id, unsigned val);
|
||||
|
||||
/**
|
||||
\brief Abstract assertion-set strategy.
|
||||
*/
|
||||
class assertion_set_strategy {
|
||||
unsigned m_ref_count;
|
||||
public:
|
||||
assertion_set_strategy():m_ref_count(0) {}
|
||||
virtual ~assertion_set_strategy() {}
|
||||
void inc_ref() { m_ref_count++; }
|
||||
void dec_ref() { SASSERT(m_ref_count > 0); m_ref_count--; if (m_ref_count == 0) dealloc(this); }
|
||||
virtual void updt_params(params_ref const & p) {}
|
||||
virtual void collect_param_descrs(param_descrs & r) {}
|
||||
void cancel();
|
||||
void reset_cancel();
|
||||
virtual void set_cancel(bool f) {}
|
||||
virtual void operator()(assertion_set & s, model_converter_ref & mc) = 0;
|
||||
virtual void collect_statistics(statistics & st) const {}
|
||||
virtual void reset_statistics() {}
|
||||
virtual void cleanup() = 0;
|
||||
virtual void reset() { cleanup(); }
|
||||
// for backward compatibility
|
||||
virtual void set_front_end_params(front_end_params & p) {}
|
||||
virtual void set_logic(symbol const & l) {}
|
||||
virtual void set_progress_callback(progress_callback * callback) {}
|
||||
};
|
||||
|
||||
bool is_equal(assertion_set const & s1, assertion_set const & s2);
|
||||
|
||||
// dummy for using ref_vector
|
||||
struct assertion_set_strategy_context {
|
||||
static void inc_ref(assertion_set_strategy * st) { st->inc_ref(); }
|
||||
static void dec_ref(assertion_set_strategy * st) { st->dec_ref(); }
|
||||
};
|
||||
|
||||
typedef assertion_set_strategy as_st;
|
||||
typedef assertion_set_strategy_context as_st_ctx;
|
||||
|
||||
typedef ref<as_st> as_st_ref;
|
||||
typedef ref_vector<as_st, as_st_ctx> as_st_ref_vector;
|
||||
typedef ref_buffer<as_st, as_st_ctx> as_st_ref_buffer;
|
||||
|
||||
as_st * and_then(unsigned num, as_st * const * sts);
|
||||
as_st * and_then(as_st * st1, as_st * st2);
|
||||
as_st * and_then(as_st * st1, as_st * st2, as_st * st3);
|
||||
as_st * and_then(as_st * st1, as_st * st2, as_st * st3, as_st * st4);
|
||||
as_st * and_then(as_st * st1, as_st * st2, as_st * st3, as_st * st4, as_st * st5);
|
||||
as_st * and_then(as_st * st1, as_st * st2, as_st * st3, as_st * st4, as_st * st5, as_st * st6);
|
||||
as_st * and_then(as_st * st1, as_st * st2, as_st * st3, as_st * st4, as_st * st5, as_st * st6, as_st * st7);
|
||||
as_st * and_then(as_st * st1, as_st * st2, as_st * st3, as_st * st4, as_st * st5, as_st * st6, as_st * st7, as_st * st8);
|
||||
as_st * and_then(as_st * st1, as_st * st2, as_st * st3, as_st * st4, as_st * st5, as_st * st6, as_st * st7, as_st * st8, as_st * st9);
|
||||
as_st * and_then(as_st * st1, as_st * st2, as_st * st3, as_st * st4, as_st * st5, as_st * st6, as_st * st7, as_st * st8, as_st * st9, as_st * st10);
|
||||
|
||||
as_st * or_else(unsigned num, as_st * const * sts);
|
||||
as_st * or_else(as_st * st1, as_st * st2);
|
||||
as_st * or_else(as_st * st1, as_st * st2, as_st * st3);
|
||||
as_st * or_else(as_st * st1, as_st * st2, as_st * st3, as_st * st4);
|
||||
as_st * or_else(as_st * st1, as_st * st2, as_st * st3, as_st * st4, as_st * st5);
|
||||
as_st * or_else(as_st * st1, as_st * st2, as_st * st3, as_st * st4, as_st * st5, as_st * st6);
|
||||
as_st * or_else(as_st * st1, as_st * st2, as_st * st3, as_st * st4, as_st * st5, as_st * st6, as_st * st7);
|
||||
as_st * or_else(as_st * st1, as_st * st2, as_st * st3, as_st * st4, as_st * st5, as_st * st6, as_st * st7, as_st * st8);
|
||||
as_st * or_else(as_st * st1, as_st * st2, as_st * st3, as_st * st4, as_st * st5, as_st * st6, as_st * st7, as_st * st8, as_st * st9);
|
||||
as_st * or_else(as_st * st1, as_st * st2, as_st * st3, as_st * st4, as_st * st5, as_st * st6, as_st * st7, as_st * st8, as_st * st9, as_st * st10);
|
||||
|
||||
as_st * par(unsigned num, as_st * const * sts);
|
||||
as_st * par(as_st * st1, as_st * st2);
|
||||
as_st * par(as_st * st1, as_st * st2, as_st * st3);
|
||||
as_st * par(as_st * st1, as_st * st2, as_st * st3, as_st * st4);
|
||||
|
||||
as_st * round_robin(unsigned num, as_st * const * sts, unsigned start, unsigned end, unsigned delta);
|
||||
as_st * round_robin(as_st * st1, as_st * st2, unsigned start, unsigned end, unsigned delta);
|
||||
as_st * round_robin(as_st * st1, as_st * st2, as_st * st3, unsigned start, unsigned end, unsigned delta);
|
||||
as_st * round_robin(as_st * st1, as_st * st2, as_st * st3, as_st * st4, unsigned start, unsigned end, unsigned delta);
|
||||
|
||||
as_st * try_for(as_st * st, unsigned msecs);
|
||||
as_st * clean(as_st * st);
|
||||
as_st * using_params(as_st * st, params_ref const & p);
|
||||
as_st * noop();
|
||||
as_st * trace_mc(as_st * st);
|
||||
|
||||
as_st * filter_is_sat(as_st* st, bool const& unless_condition);
|
||||
as_st * filter_is_unsat(as_st* st, bool const& unless_condition);
|
||||
|
||||
as_st * mk_report_verbose_st(char const* msg, unsigned lvl);
|
||||
|
||||
as_st * repeat(as_st * st, unsigned max = UINT_MAX);
|
||||
|
||||
class wrapper_as_st : public as_st {
|
||||
protected:
|
||||
as_st * m_st;
|
||||
public:
|
||||
wrapper_as_st(as_st * s): m_st(s) { SASSERT(s); s->inc_ref(); }
|
||||
virtual ~wrapper_as_st();
|
||||
|
||||
virtual void operator()(assertion_set& s, model_converter_ref& mc) { (*m_st)(s, mc); }
|
||||
virtual void cleanup(void) { m_st->cleanup(); }
|
||||
virtual void collect_statistics(statistics & st) const { m_st->collect_statistics(st); }
|
||||
virtual void reset_statistics() { m_st->reset_statistics(); }
|
||||
virtual void set_front_end_params(front_end_params & p) { m_st->set_front_end_params(p); }
|
||||
virtual void updt_params(params_ref const & p) { m_st->updt_params(p); }
|
||||
virtual void collect_param_descrs(param_descrs & r) { m_st->collect_param_descrs(r); }
|
||||
virtual void reset() { m_st->reset(); }
|
||||
virtual void set_logic(symbol const& l) { m_st->set_logic(l); }
|
||||
virtual void set_progress_callback(progress_callback * callback) { m_st->set_progress_callback(callback); }
|
||||
|
||||
protected:
|
||||
virtual void set_cancel(bool f) { if (m_st) m_st->set_cancel(f); }
|
||||
};
|
||||
|
||||
|
||||
class as_test {
|
||||
unsigned m_ref_count;
|
||||
public:
|
||||
as_test():m_ref_count(0) {}
|
||||
void inc_ref() { m_ref_count++; }
|
||||
void dec_ref() { SASSERT(m_ref_count > 0); m_ref_count--; if (m_ref_count == 0) dealloc(this); }
|
||||
virtual bool operator()(assertion_set const & s) const = 0;
|
||||
};
|
||||
|
||||
as_test * check_mem(unsigned l);
|
||||
as_test * check_as_size(unsigned l);
|
||||
as_test * check_decided();
|
||||
as_st * cond(as_test * c, as_st * t, as_st * e);
|
||||
|
||||
as_st * mk_smt_solver_core(bool candidate_models = false);
|
||||
as_st * mk_smt_solver(bool auto_config = true, bool candidate_models = false);
|
||||
|
||||
void exec(as_st * st, assertion_set & s, model_converter_ref & mc);
|
||||
lbool check_sat(as_st * st, assertion_set & s, model_ref & md, proof_ref & pr, std::string & reason_unknown);
|
||||
|
||||
class assertion_set_strategy_factory {
|
||||
public:
|
||||
virtual ~assertion_set_strategy_factory() {}
|
||||
virtual as_st * operator()(ast_manager & m, params_ref const & p) = 0;
|
||||
};
|
||||
|
||||
typedef assertion_set_strategy_factory as_st_f;
|
||||
|
||||
as_st * fail();
|
||||
as_st * fail_if_not_decided(as_st * st);
|
||||
as_st * fail_if_sat();
|
||||
as_st * fail_if_unsat();
|
||||
as_st * fail_if_not_small(unsigned sz);
|
||||
as_st * fail_if_not_small_set(unsigned sz);
|
||||
|
||||
#define MK_FAIL_IF(NAME, TEST, MSG) \
|
||||
class NAME ## _st : public assertion_set_strategy { \
|
||||
public: \
|
||||
virtual void operator()(assertion_set & s, model_converter_ref & mc) { if (TEST) throw strategy_exception(MSG); } \
|
||||
virtual void cleanup() {} \
|
||||
}; \
|
||||
inline as_st * NAME() { return alloc(NAME ## _st); }
|
||||
|
||||
as_st * par_or(ast_manager & m, unsigned num, as_st_f * const * stfs);
|
||||
|
||||
#define MK_ST_FACTORY(NAME, CODE) \
|
||||
class NAME : public assertion_set_strategy_factory { \
|
||||
public: \
|
||||
virtual ~NAME() {} \
|
||||
virtual as_st * operator()(ast_manager & m, params_ref const & p) { CODE } \
|
||||
};
|
||||
|
||||
#define MK_SIMPLE_ST_FACTORY(NAME, ST) MK_ST_FACTORY(NAME, return ST;)
|
||||
|
||||
MK_SIMPLE_ST_FACTORY(smt_solver_stf, mk_smt_solver());
|
||||
|
||||
struct is_qfbv_test : public as_test {
|
||||
virtual bool operator()(assertion_set const & s) const { return is_qfbv(s); }
|
||||
};
|
||||
|
||||
struct is_qflia_test : public as_test {
|
||||
virtual bool operator()(assertion_set const & s) const { return is_qflia(s); }
|
||||
};
|
||||
|
||||
struct is_qflra_test : public as_test {
|
||||
virtual bool operator()(assertion_set const & s) const { return is_qflra(s); }
|
||||
};
|
||||
|
||||
inline as_test * is_qfbv() { return alloc(is_qfbv_test); }
|
||||
inline as_test * is_qflia() { return alloc(is_qflia_test); }
|
||||
inline as_test * is_qflra() { return alloc(is_qflra_test); }
|
||||
|
||||
#endif
|
220
lib/assertion_set_util.cpp
Normal file
220
lib/assertion_set_util.cpp
Normal file
|
@ -0,0 +1,220 @@
|
|||
/*++
|
||||
Copyright (c) 2011 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
assertion_set_util.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Assertion set goodies
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2011-04-28
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include"assertion_set_util.h"
|
||||
#include"well_sorted.h"
|
||||
#include"for_each_expr.h"
|
||||
#include"bv_decl_plugin.h"
|
||||
#include"arith_decl_plugin.h"
|
||||
|
||||
void as_shared_occs::operator()(assertion_set const & s) {
|
||||
m_occs.reset();
|
||||
shared_occs_mark visited;
|
||||
unsigned sz = s.size();
|
||||
for (unsigned i = 0; i < sz; i++) {
|
||||
expr * t = s.form(i);
|
||||
m_occs(t, visited);
|
||||
}
|
||||
}
|
||||
|
||||
bool is_well_sorted(assertion_set const & s) {
|
||||
unsigned sz = s.size();
|
||||
for (unsigned i = 0; i < sz; i++) {
|
||||
expr * t = s.form(i);
|
||||
if (!is_well_sorted(s.m(), t))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
struct is_non_propositional {
|
||||
struct found {};
|
||||
ast_manager & m;
|
||||
|
||||
is_non_propositional(ast_manager & _m):m(_m) {}
|
||||
void operator()(var *) { throw found(); }
|
||||
void operator()(quantifier *) { throw found(); }
|
||||
void operator()(app * n) {
|
||||
if (!m.is_bool(n))
|
||||
throw found();
|
||||
|
||||
family_id fid = n->get_family_id();
|
||||
if (fid == m.get_basic_family_id())
|
||||
return;
|
||||
|
||||
if (is_uninterp_const(n))
|
||||
return;
|
||||
|
||||
throw found();
|
||||
}
|
||||
};
|
||||
|
||||
struct is_non_qfbv {
|
||||
struct found {};
|
||||
ast_manager & m;
|
||||
bv_util u;
|
||||
|
||||
is_non_qfbv(ast_manager & _m):m(_m), u(m) {}
|
||||
|
||||
void operator()(var *) { throw found(); }
|
||||
|
||||
void operator()(quantifier *) { throw found(); }
|
||||
|
||||
void operator()(app * n) {
|
||||
if (!m.is_bool(n) && !u.is_bv(n))
|
||||
throw found();
|
||||
family_id fid = n->get_family_id();
|
||||
if (fid == m.get_basic_family_id())
|
||||
return;
|
||||
if (fid == u.get_family_id())
|
||||
return;
|
||||
if (is_uninterp_const(n))
|
||||
return;
|
||||
|
||||
throw found();
|
||||
}
|
||||
};
|
||||
|
||||
bool is_propositional(assertion_set const & s) {
|
||||
return !test<is_non_propositional>(s);
|
||||
}
|
||||
|
||||
bool is_qfbv(assertion_set const & s) {
|
||||
return !test<is_non_qfbv>(s);
|
||||
}
|
||||
|
||||
struct is_non_qflira {
|
||||
struct found {};
|
||||
ast_manager & m;
|
||||
arith_util u;
|
||||
bool m_int;
|
||||
bool m_real;
|
||||
|
||||
is_non_qflira(ast_manager & _m, bool _int, bool _real):m(_m), u(m), m_int(_int), m_real(_real) {}
|
||||
|
||||
void operator()(var *) { throw found(); }
|
||||
|
||||
void operator()(quantifier *) { throw found(); }
|
||||
|
||||
bool compatible_sort(app * n) const {
|
||||
if (m.is_bool(n))
|
||||
return true;
|
||||
if (m_int && u.is_int(n))
|
||||
return true;
|
||||
if (m_real && u.is_real(n))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void operator()(app * n) {
|
||||
if (!compatible_sort(n))
|
||||
throw found();
|
||||
family_id fid = n->get_family_id();
|
||||
if (fid == m.get_basic_family_id())
|
||||
return;
|
||||
if (fid == u.get_family_id()) {
|
||||
switch (n->get_decl_kind()) {
|
||||
case OP_LE: case OP_GE: case OP_LT: case OP_GT:
|
||||
case OP_ADD: case OP_NUM:
|
||||
return;
|
||||
case OP_MUL:
|
||||
if (n->get_num_args() != 2)
|
||||
throw found();
|
||||
if (!u.is_numeral(n->get_arg(0)))
|
||||
throw found();
|
||||
return;
|
||||
case OP_TO_REAL:
|
||||
if (!m_real)
|
||||
throw found();
|
||||
break;
|
||||
default:
|
||||
throw found();
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (is_uninterp_const(n))
|
||||
return;
|
||||
throw found();
|
||||
}
|
||||
};
|
||||
|
||||
bool is_qflia(assertion_set const & s) {
|
||||
is_non_qflira proc(s.m(), true, false);
|
||||
return !test(s, proc);
|
||||
}
|
||||
|
||||
bool is_qflra(assertion_set const & s) {
|
||||
is_non_qflira proc(s.m(), false, true);
|
||||
return !test(s, proc);
|
||||
}
|
||||
|
||||
bool is_qflira(assertion_set const & s) {
|
||||
is_non_qflira proc(s.m(), true, true);
|
||||
return !test(s, proc);
|
||||
}
|
||||
|
||||
bool is_lp(assertion_set const & s) {
|
||||
ast_manager & m = s.m();
|
||||
arith_util u(m);
|
||||
unsigned sz = s.size();
|
||||
for (unsigned i = 0; i < sz; i++) {
|
||||
expr * f = s.form(i);
|
||||
bool sign = false;
|
||||
while (m.is_not(f, f))
|
||||
sign = !sign;
|
||||
if (m.is_eq(f) && !sign) {
|
||||
if (m.get_sort(to_app(f)->get_arg(0))->get_family_id() != u.get_family_id())
|
||||
return false;
|
||||
continue;
|
||||
}
|
||||
if (u.is_le(f) || u.is_ge(f) || u.is_lt(f) || u.is_gt(f))
|
||||
continue;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool is_ilp(assertion_set const & s) {
|
||||
if (!is_qflia(s))
|
||||
return false;
|
||||
if (has_term_ite(s))
|
||||
return false;
|
||||
return is_lp(s);
|
||||
}
|
||||
|
||||
bool is_mip(assertion_set const & s) {
|
||||
if (!is_qflira(s))
|
||||
return false;
|
||||
if (has_term_ite(s))
|
||||
return false;
|
||||
return is_lp(s);
|
||||
}
|
||||
|
||||
struct has_term_ite_proc {
|
||||
struct found {};
|
||||
ast_manager & m;
|
||||
has_term_ite_proc(ast_manager & _m):m(_m) {}
|
||||
void operator()(var *) {}
|
||||
void operator()(quantifier *) {}
|
||||
void operator()(app * n) { if (m.is_term_ite(n)) throw found(); }
|
||||
};
|
||||
|
||||
bool has_term_ite(assertion_set const & s) {
|
||||
return test<has_term_ite_proc>(s);
|
||||
}
|
||||
|
91
lib/assertion_set_util.h
Normal file
91
lib/assertion_set_util.h
Normal file
|
@ -0,0 +1,91 @@
|
|||
/*++
|
||||
Copyright (c) 2011 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
assertion_set_util.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Assertion set goodies
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2011-04-28
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _ASSERTION_SET_UTIL_H_
|
||||
#define _ASSERTION_SET_UTIL_H_
|
||||
|
||||
#include"assertion_set.h"
|
||||
#include"shared_occs.h"
|
||||
|
||||
/**
|
||||
\brief Functor for computing the set of shared occurrences in an assertion set.
|
||||
|
||||
It is essentially a wrapper for shared_occs functor.
|
||||
*/
|
||||
class as_shared_occs {
|
||||
shared_occs m_occs;
|
||||
public:
|
||||
as_shared_occs(ast_manager & m, bool track_atomic = false, bool visit_quantifiers = true, bool visit_patterns = false):
|
||||
m_occs(m, track_atomic, visit_quantifiers, visit_patterns) {
|
||||
}
|
||||
void operator()(assertion_set const & s);
|
||||
bool is_shared(expr * t) { return m_occs.is_shared(t); }
|
||||
unsigned num_shared() const { return m_occs.num_shared(); }
|
||||
void reset() { return m_occs.reset(); }
|
||||
void cleanup() { return m_occs.cleanup(); }
|
||||
void display(std::ostream & out, ast_manager & m) const { m_occs.display(out, m); }
|
||||
};
|
||||
|
||||
bool is_well_sorted(assertion_set const & s);
|
||||
|
||||
// Return true if the assertion set is propositional logic
|
||||
bool is_propositional(assertion_set const & s);
|
||||
|
||||
// Return true if the assertion set is in QF_BV
|
||||
bool is_qfbv(assertion_set const & s);
|
||||
|
||||
// Return true if the assertion set is in QF_LIA
|
||||
bool is_qflia(assertion_set const & s);
|
||||
|
||||
// Return true if the assertion set is in QF_LRA
|
||||
bool is_qflra(assertion_set const & s);
|
||||
|
||||
// Return true if the assertion set is in QF_LIRA
|
||||
bool is_qflira(assertion_set const & s);
|
||||
|
||||
// Return true if the assertion set is in ILP problem (that is QF_LIA without boolean structure)
|
||||
bool is_ilp(assertion_set const & s);
|
||||
|
||||
// Return true if the assertion set is in MIP problem (that is QF_LIRA without boolean structure)
|
||||
bool is_mip(assertion_set const & s);
|
||||
|
||||
bool has_term_ite(assertion_set const & s);
|
||||
|
||||
inline bool is_decided(assertion_set const & s) { return s.size() == 0 || s.inconsistent(); }
|
||||
|
||||
template<typename Predicate>
|
||||
bool test(assertion_set const & s, Predicate & proc) {
|
||||
expr_fast_mark1 visited;
|
||||
try {
|
||||
unsigned sz = s.size();
|
||||
for (unsigned i = 0; i < sz; i++)
|
||||
quick_for_each_expr(proc, visited, s.form(i));
|
||||
}
|
||||
catch (typename Predicate::found) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename Predicate>
|
||||
bool test(assertion_set const & s) {
|
||||
Predicate proc(s.m());
|
||||
return test(s, proc);
|
||||
}
|
||||
|
||||
#endif
|
314
lib/assertion_stack.cpp
Normal file
314
lib/assertion_stack.cpp
Normal file
|
@ -0,0 +1,314 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
assertion_stack.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Assertion stacks
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2012-02-17
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include"assertion_stack.h"
|
||||
#include"well_sorted.h"
|
||||
#include"ast_smt2_pp.h"
|
||||
#include"ref_util.h"
|
||||
|
||||
assertion_stack::assertion_stack(ast_manager & m, bool models_enabled, bool core_enabled):
|
||||
m_manager(m),
|
||||
m_forbidden(m),
|
||||
m_csubst(m, core_enabled),
|
||||
m_fsubst(m, core_enabled) {
|
||||
init(m.proofs_enabled(), models_enabled, core_enabled);
|
||||
}
|
||||
|
||||
assertion_stack::assertion_stack(ast_manager & m, bool proofs_enabled, bool models_enabled, bool core_enabled):
|
||||
m_manager(m),
|
||||
m_forbidden(m),
|
||||
m_csubst(m, core_enabled, proofs_enabled),
|
||||
m_fsubst(m, core_enabled, proofs_enabled) {
|
||||
init(proofs_enabled, models_enabled, core_enabled);
|
||||
}
|
||||
|
||||
void assertion_stack::init(bool proofs_enabled, bool models_enabled, bool core_enabled) {
|
||||
m_ref_count = 0;
|
||||
m_models_enabled = models_enabled;
|
||||
m_proofs_enabled = proofs_enabled;
|
||||
m_core_enabled = core_enabled;
|
||||
m_inconsistent = false;
|
||||
m_form_qhead = 0;
|
||||
}
|
||||
|
||||
assertion_stack::~assertion_stack() {
|
||||
reset();
|
||||
}
|
||||
|
||||
void assertion_stack::reset() {
|
||||
m_inconsistent = false;
|
||||
m_form_qhead = 0;
|
||||
m_mc_qhead = 0;
|
||||
dec_ref_collection_values(m_manager, m_forms);
|
||||
dec_ref_collection_values(m_manager, m_proofs);
|
||||
dec_ref_collection_values(m_manager, m_deps);
|
||||
m_forbidden_set.reset();
|
||||
m_forbidden.reset();
|
||||
m_csubst.reset();
|
||||
m_fsubst.reset();
|
||||
m_mc.reset();
|
||||
m_scopes.reset();
|
||||
}
|
||||
|
||||
void assertion_stack::expand(expr * f, proof * pr, expr_dependency * dep, expr_ref & new_f, proof_ref & new_pr, expr_dependency_ref & new_dep) {
|
||||
// TODO: expand definitions
|
||||
new_f = f;
|
||||
new_pr = pr;
|
||||
new_dep = dep;
|
||||
}
|
||||
|
||||
void assertion_stack::push_back(expr * f, proof * pr, expr_dependency * d) {
|
||||
if (m().is_true(f))
|
||||
return;
|
||||
if (m().is_false(f)) {
|
||||
m_inconsistent = true;
|
||||
}
|
||||
else {
|
||||
SASSERT(!m_inconsistent);
|
||||
}
|
||||
m().inc_ref(f);
|
||||
m_forms.push_back(f);
|
||||
if (proofs_enabled()) {
|
||||
m().inc_ref(pr);
|
||||
m_proofs.push_back(pr);
|
||||
}
|
||||
if (unsat_core_enabled()) {
|
||||
m().inc_ref(d);
|
||||
m_deps.push_back(d);
|
||||
}
|
||||
}
|
||||
|
||||
void assertion_stack::quick_process(bool save_first, expr * & f, expr_dependency * d) {
|
||||
if (!m().is_and(f) && !(m().is_not(f) && m().is_or(to_app(f)->get_arg(0)))) {
|
||||
if (!save_first) {
|
||||
push_back(f, 0, d);
|
||||
}
|
||||
return;
|
||||
}
|
||||
typedef std::pair<expr *, bool> expr_pol;
|
||||
sbuffer<expr_pol, 64> todo;
|
||||
todo.push_back(expr_pol(f, true));
|
||||
while (!todo.empty()) {
|
||||
if (m_inconsistent)
|
||||
return;
|
||||
expr_pol p = todo.back();
|
||||
expr * curr = p.first;
|
||||
bool pol = p.second;
|
||||
todo.pop_back();
|
||||
if (pol && m().is_and(curr)) {
|
||||
app * t = to_app(curr);
|
||||
unsigned i = t->get_num_args();
|
||||
while (i > 0) {
|
||||
--i;
|
||||
todo.push_back(expr_pol(t->get_arg(i), true));
|
||||
}
|
||||
}
|
||||
else if (!pol && m().is_or(curr)) {
|
||||
app * t = to_app(curr);
|
||||
unsigned i = t->get_num_args();
|
||||
while (i > 0) {
|
||||
--i;
|
||||
todo.push_back(expr_pol(t->get_arg(i), false));
|
||||
}
|
||||
}
|
||||
else if (m().is_not(curr)) {
|
||||
todo.push_back(expr_pol(to_app(curr)->get_arg(0), !pol));
|
||||
}
|
||||
else {
|
||||
if (!pol)
|
||||
curr = m().mk_not(curr);
|
||||
if (save_first) {
|
||||
f = curr;
|
||||
save_first = false;
|
||||
}
|
||||
else {
|
||||
push_back(curr, 0, d);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void assertion_stack::process_and(bool save_first, app * f, proof * pr, expr_dependency * d, expr_ref & out_f, proof_ref & out_pr) {
|
||||
unsigned num = f->get_num_args();
|
||||
for (unsigned i = 0; i < num; i++) {
|
||||
if (m_inconsistent)
|
||||
return;
|
||||
slow_process(save_first && i == 0, f->get_arg(i), m().mk_and_elim(pr, i), d, out_f, out_pr);
|
||||
}
|
||||
}
|
||||
|
||||
void assertion_stack::process_not_or(bool save_first, app * f, proof * pr, expr_dependency * d, expr_ref & out_f, proof_ref & out_pr) {
|
||||
unsigned num = f->get_num_args();
|
||||
for (unsigned i = 0; i < num; i++) {
|
||||
if (m_inconsistent)
|
||||
return;
|
||||
expr * child = f->get_arg(i);
|
||||
if (m().is_not(child)) {
|
||||
expr * not_child = to_app(child)->get_arg(0);
|
||||
slow_process(save_first && i == 0, not_child, m().mk_not_or_elim(pr, i), d, out_f, out_pr);
|
||||
}
|
||||
else {
|
||||
expr_ref not_child(m());
|
||||
not_child = m().mk_not(child);
|
||||
slow_process(save_first && i == 0, not_child, m().mk_not_or_elim(pr, i), d, out_f, out_pr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void assertion_stack::slow_process(bool save_first, expr * f, proof * pr, expr_dependency * d, expr_ref & out_f, proof_ref & out_pr) {
|
||||
if (m().is_and(f))
|
||||
process_and(save_first, to_app(f), pr, d, out_f, out_pr);
|
||||
else if (m().is_not(f) && m().is_or(to_app(f)->get_arg(0)))
|
||||
process_not_or(save_first, to_app(to_app(f)->get_arg(0)), pr, d, out_f, out_pr);
|
||||
else if (save_first) {
|
||||
out_f = f;
|
||||
out_pr = pr;
|
||||
}
|
||||
else {
|
||||
push_back(f, pr, d);
|
||||
}
|
||||
}
|
||||
|
||||
void assertion_stack::slow_process(expr * f, proof * pr, expr_dependency * d) {
|
||||
expr_ref out_f(m());
|
||||
proof_ref out_pr(m());
|
||||
slow_process(false, f, pr, d, out_f, out_pr);
|
||||
}
|
||||
|
||||
|
||||
void assertion_stack::assert_expr(expr * f, proof * pr, expr_dependency * d) {
|
||||
SASSERT(proofs_enabled() == (pr != 0 && !m().is_undef_proof(pr)));
|
||||
if (m_inconsistent)
|
||||
return;
|
||||
expr_ref new_f(m()); proof_ref new_pr(m()); expr_dependency_ref new_d(m());
|
||||
expand(f, pr, d, new_f, new_pr, new_d);
|
||||
if (proofs_enabled())
|
||||
slow_process(f, pr, d);
|
||||
else
|
||||
quick_process(false, f, d);
|
||||
}
|
||||
|
||||
#ifdef Z3DEBUG
|
||||
// bool assertion_stack::is_expanded(expr * f) {
|
||||
// }
|
||||
#endif
|
||||
|
||||
void assertion_stack::update(unsigned i, expr * f, proof * pr, expr_dependency * d) {
|
||||
SASSERT(i >= m_form_qhead);
|
||||
SASSERT(proofs_enabled() == (pr != 0 && !m().is_undef_proof(pr)));
|
||||
if (m_inconsistent)
|
||||
return;
|
||||
if (proofs_enabled()) {
|
||||
expr_ref out_f(m());
|
||||
proof_ref out_pr(m());
|
||||
slow_process(true, f, pr, d, out_f, out_pr);
|
||||
if (!m_inconsistent) {
|
||||
if (m().is_false(out_f)) {
|
||||
push_back(out_f, out_pr, d);
|
||||
}
|
||||
else {
|
||||
m().inc_ref(out_f);
|
||||
m().dec_ref(m_forms[i]);
|
||||
m_forms[i] = out_f;
|
||||
|
||||
m().inc_ref(out_pr);
|
||||
m().dec_ref(m_proofs[i]);
|
||||
m_proofs[i] = out_pr;
|
||||
|
||||
if (unsat_core_enabled()) {
|
||||
m().inc_ref(d);
|
||||
m().dec_ref(m_deps[i]);
|
||||
m_deps[i] = d;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
quick_process(true, f, d);
|
||||
if (!m_inconsistent) {
|
||||
if (m().is_false(f)) {
|
||||
push_back(f, 0, d);
|
||||
}
|
||||
else {
|
||||
m().inc_ref(f);
|
||||
m().dec_ref(m_forms[i]);
|
||||
m_forms[i] = f;
|
||||
|
||||
if (unsat_core_enabled()) {
|
||||
m().inc_ref(d);
|
||||
m().dec_ref(m_deps[i]);
|
||||
m_deps[i] = d;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void assertion_stack::expand_and_update(unsigned i, expr * f, proof * pr, expr_dependency * d) {
|
||||
SASSERT(i >= m_form_qhead);
|
||||
SASSERT(proofs_enabled() == (pr != 0 && !m().is_undef_proof(pr)));
|
||||
if (m_inconsistent)
|
||||
return;
|
||||
expr_ref new_f(m()); proof_ref new_pr(m()); expr_dependency_ref new_d(m());
|
||||
expand(f, pr, d, new_f, new_pr, new_d);
|
||||
update(i, new_f, new_pr, new_d);
|
||||
}
|
||||
|
||||
void assertion_stack::push() {
|
||||
}
|
||||
|
||||
void assertion_stack::pop(unsigned num_scopes) {
|
||||
}
|
||||
|
||||
void assertion_stack::commit() {
|
||||
}
|
||||
|
||||
void assertion_stack::add_filter(func_decl * f) const {
|
||||
}
|
||||
|
||||
void assertion_stack::add_definition(app * c, expr * def, proof * pr, expr_dependency * dep) {
|
||||
|
||||
}
|
||||
|
||||
void assertion_stack::add_definition(func_decl * f, quantifier * q, proof * pr, expr_dependency * dep) {
|
||||
}
|
||||
|
||||
void assertion_stack::convert(model_ref & m) {
|
||||
}
|
||||
|
||||
void assertion_stack::display(std::ostream & out) const {
|
||||
out << "(assertion-stack";
|
||||
unsigned sz = size();
|
||||
for (unsigned i = 0; i < sz; i++) {
|
||||
out << "\n ";
|
||||
if (i == m_form_qhead)
|
||||
out << "==>\n";
|
||||
out << mk_ismt2_pp(form(i), m(), 2);
|
||||
}
|
||||
out << ")" << std::endl;
|
||||
}
|
||||
|
||||
bool assertion_stack::is_well_sorted() const {
|
||||
unsigned sz = size();
|
||||
for (unsigned i = 0; i < sz; i++) {
|
||||
expr * t = form(i);
|
||||
if (!::is_well_sorted(m(), t))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
141
lib/assertion_stack.h
Normal file
141
lib/assertion_stack.h
Normal file
|
@ -0,0 +1,141 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
assertion_stack.h
|
||||
|
||||
Abstract:
|
||||
|
||||
It should be viewed as the "goal" object for incremental solvers.
|
||||
The main difference is the support of push/pop operations. Like a
|
||||
goal, an assertion_stack contains expressions, their proofs (if
|
||||
proof generation is enabled), and dependencies (if unsat core
|
||||
generation is enabled).
|
||||
|
||||
The assertions on the stack are grouped by scope levels. Scoped
|
||||
levels are created using push, and removed using pop.
|
||||
|
||||
Assertions may be "committed". Whenever a push is executed, all
|
||||
"uncommitted" assertions are automatically committed.
|
||||
Only uncommitted assertions can be simplified/reduced.
|
||||
|
||||
An assertion set has a limited model converter that only supports
|
||||
definitions (for variable/function elimination) and filters (for fresh
|
||||
symbols introduced by tactics).
|
||||
|
||||
Some tactics support assertion_stacks and can be applied to them.
|
||||
However, a tactic can only access the assertions on the top level.
|
||||
The assertion stack also informs the tactic which declarations
|
||||
can't be eliminated since they occur in the already committed part.
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2012-02-17
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _ASSERTION_STACK_H_
|
||||
#define _ASSERTION_STACK_H_
|
||||
|
||||
#include"ast.h"
|
||||
#include"model.h"
|
||||
#include"expr_substitution.h"
|
||||
#include"macro_substitution.h"
|
||||
|
||||
class assertion_stack {
|
||||
ast_manager & m_manager;
|
||||
unsigned m_ref_count;
|
||||
bool m_models_enabled; // model generation is enabled.
|
||||
bool m_proofs_enabled; // proof production is enabled. m_manager.proofs_enabled() must be true if m_proofs_enabled == true
|
||||
bool m_core_enabled; // unsat core extraction is enabled.
|
||||
bool m_inconsistent;
|
||||
ptr_vector<expr> m_forms;
|
||||
ptr_vector<proof> m_proofs;
|
||||
ptr_vector<expr_dependency> m_deps;
|
||||
unsigned m_form_qhead; // position of first uncommitted assertion
|
||||
unsigned m_mc_qhead;
|
||||
|
||||
// Set of declarations that can't be eliminated
|
||||
obj_hashtable<func_decl> m_forbidden_set;
|
||||
func_decl_ref_vector m_forbidden;
|
||||
|
||||
// Limited model converter support, it supports only extensions
|
||||
// and filters.
|
||||
// It should be viewed as combination of extension_model_converter and
|
||||
// filter_model_converter for goals.
|
||||
expr_substitution m_csubst; // substitution for eliminated constants
|
||||
macro_substitution m_fsubst; // substitution for eliminated functions
|
||||
|
||||
// Model converter is just a sequence of tagged pointers.
|
||||
// Tag 0 (extension) func_decl was eliminated, and its definition is in m_vsubst or m_fsubst.
|
||||
// Tag 1 (filter) func_decl was introduced by tactic, and must be removed from model.
|
||||
ptr_vector<func_decl> m_mc;
|
||||
|
||||
struct scope {
|
||||
unsigned m_forms_lim;
|
||||
unsigned m_forbidden_vars_lim;
|
||||
unsigned m_mc_lim;
|
||||
bool m_inconsistent_old;
|
||||
};
|
||||
|
||||
svector<scope> m_scopes;
|
||||
|
||||
void init(bool proofs_enabled, bool models_enabled, bool core_enabled);
|
||||
void expand(expr * f, proof * pr, expr_dependency * dep, expr_ref & new_f, proof_ref & new_pr, expr_dependency_ref & new_dep);
|
||||
void push_back(expr * f, proof * pr, expr_dependency * d);
|
||||
void quick_process(bool save_first, expr * & f, expr_dependency * d);
|
||||
void process_and(bool save_first, app * f, proof * pr, expr_dependency * d, expr_ref & out_f, proof_ref & out_pr);
|
||||
void process_not_or(bool save_first, app * f, proof * pr, expr_dependency * d, expr_ref & out_f, proof_ref & out_pr);
|
||||
void slow_process(bool save_first, expr * f, proof * pr, expr_dependency * d, expr_ref & out_f, proof_ref & out_pr);
|
||||
void slow_process(expr * f, proof * pr, expr_dependency * d);
|
||||
|
||||
public:
|
||||
assertion_stack(ast_manager & m, bool models_enabled = true, bool core_enabled = true);
|
||||
assertion_stack(ast_manager & m, bool proofs_enabled, bool models_enabled, bool core_enabled);
|
||||
~assertion_stack();
|
||||
|
||||
void reset();
|
||||
|
||||
void inc_ref() { ++m_ref_count; }
|
||||
void dec_ref() { --m_ref_count; if (m_ref_count == 0) dealloc(this); }
|
||||
|
||||
ast_manager & m() const { return m_manager; }
|
||||
|
||||
bool models_enabled() const { return m_models_enabled; }
|
||||
bool proofs_enabled() const { return m_proofs_enabled; }
|
||||
bool unsat_core_enabled() const { return m_core_enabled; }
|
||||
bool inconsistent() const { return m_inconsistent; }
|
||||
|
||||
unsigned size() const { return m_forms.size(); }
|
||||
unsigned qhead() const { return m_form_qhead; }
|
||||
expr * form(unsigned i) const { return m_forms[i]; }
|
||||
proof * pr(unsigned i) const { return proofs_enabled() ? static_cast<proof*>(m_proofs[i]) : 0; }
|
||||
expr_dependency * dep(unsigned i) const { return unsat_core_enabled() ? m_deps[i] : 0; }
|
||||
|
||||
void assert_expr(expr * f, proof * pr, expr_dependency * d);
|
||||
void assert_expr(expr * f) {
|
||||
assert_expr(f, proofs_enabled() ? m().mk_asserted(f) : 0, 0);
|
||||
}
|
||||
void update(unsigned i, expr * f, proof * pr = 0, expr_dependency * dep = 0);
|
||||
void expand_and_update(unsigned i, expr * f, proof * pr = 0, expr_dependency * d = 0);
|
||||
|
||||
void commit();
|
||||
void push();
|
||||
void pop(unsigned num_scopes);
|
||||
unsigned scope_lvl() const { return m_scopes.size(); }
|
||||
|
||||
bool is_well_sorted() const;
|
||||
|
||||
bool is_forbidden(func_decl * f) const { return m_forbidden_set.contains(f); }
|
||||
void add_filter(func_decl * f) const;
|
||||
void add_definition(app * c, expr * def, proof * pr, expr_dependency * dep);
|
||||
void add_definition(func_decl * f, quantifier * q, proof * pr, expr_dependency * dep);
|
||||
|
||||
void convert(model_ref & m);
|
||||
|
||||
void display(std::ostream & out) const;
|
||||
};
|
||||
|
||||
#endif
|
2903
lib/ast.cpp
Normal file
2903
lib/ast.cpp
Normal file
File diff suppressed because it is too large
Load diff
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue