3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-06-06 22:23:22 +00:00

Integrated structured branch into unstable branch (the official 'working in progress' branch)

Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
Leonardo de Moura 2012-10-24 13:19:19 -07:00
commit 3da69a4f1b
1502 changed files with 2524 additions and 5113 deletions

219
src/api/api_arith.cpp Normal file
View 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
src/api/api_array.cpp Normal file
View 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, &param, 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, &param, 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, &param, 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
src/api/api_ast.cpp Normal file

File diff suppressed because it is too large Load diff

169
src/api/api_ast_map.cpp Normal file
View 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
src/api/api_ast_map.h Normal file
View 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
src/api/api_ast_vector.cpp Normal file
View 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
src/api/api_ast_vector.h Normal file
View 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
src/api/api_bv.cpp Normal file
View 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);
}
};

3525
src/api/api_commands.cpp Normal file

File diff suppressed because it is too large Load diff

View 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;
}
};

View 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

572
src/api/api_context.cpp Normal file
View file

@ -0,0 +1,572 @@
/*++
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"
#include"reg_decl_plugins.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) {
reg_decl_plugins(m);
}
// ------------------------
//
// 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
src/api/api_context.h Normal file
View 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
src/api/api_datalog.cpp Normal file
View 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
src/api/api_datalog.h Normal file
View 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
src/api/api_datatype.cpp Normal file
View 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
src/api/api_goal.cpp Normal file
View 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
src/api/api_goal.h Normal file
View 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
src/api/api_log.cpp Normal file
View 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;
}
}
}

3355
src/api/api_log_macros.cpp Normal file

File diff suppressed because it is too large Load diff

989
src/api/api_log_macros.h Normal file
View file

@ -0,0 +1,989 @@
// Automatically generated file, generator: update_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_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_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_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_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_param_descrs_to_string(Z3_context a0, Z3_param_descrs a1);
#define LOG_Z3_param_descrs_to_string(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_param_descrs_to_string(_ARG0, _ARG1); }
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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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); }
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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_mk_polynomial_manager(Z3_context a0);
#define LOG_Z3_mk_polynomial_manager(_ARG0) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_polynomial_manager(_ARG0); }
void log_Z3_del_polynomial_manager(Z3_context a0, Z3_polynomial_manager a1);
#define LOG_Z3_del_polynomial_manager(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_del_polynomial_manager(_ARG0, _ARG1); }
void log_Z3_mk_zero_polynomial(Z3_context a0, Z3_polynomial_manager a1);
#define LOG_Z3_mk_zero_polynomial(_ARG0, _ARG1) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_mk_zero_polynomial(_ARG0, _ARG1); }
void log_Z3_polynomial_inc_ref(Z3_context a0, Z3_polynomial_manager a1, Z3_polynomial a2);
#define LOG_Z3_polynomial_inc_ref(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_polynomial_inc_ref(_ARG0, _ARG1, _ARG2); }
void log_Z3_polynomial_dec_ref(Z3_context a0, Z3_polynomial_manager a1, Z3_polynomial a2);
#define LOG_Z3_polynomial_dec_ref(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_polynomial_dec_ref(_ARG0, _ARG1, _ARG2); }
void log_Z3_polynomial_to_string(Z3_context a0, Z3_polynomial_manager a1, Z3_polynomial a2);
#define LOG_Z3_polynomial_to_string(_ARG0, _ARG1, _ARG2) z3_log_ctx _LOG_CTX; if (_LOG_CTX.enabled()) { log_Z3_polynomial_to_string(_ARG0, _ARG1, _ARG2); }

670
src/api/api_model.cpp Normal file
View 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
src/api/api_model.h Normal file
View 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
src/api/api_numeral.cpp Normal file
View 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);
}
};

199
src/api/api_params.cpp Normal file
View file

@ -0,0 +1,199 @@
/*++
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);
}
Z3_string Z3_API Z3_param_descrs_to_string(Z3_context c, Z3_param_descrs p) {
Z3_TRY;
LOG_Z3_param_descrs_to_string(c, p);
RESET_ERROR_CODE();
std::ostringstream buffer;
buffer << "(";
unsigned sz = to_param_descrs_ptr(p)->size();
for (unsigned i = 0; i < sz; i++) {
if (i > 0)
buffer << ", ";
buffer << to_param_descrs_ptr(p)->get_param_name(i);
}
buffer << ")";
return mk_c(c)->mk_external_string(buffer.str());
Z3_CATCH_RETURN("");
}
};

426
src/api/api_parsers.cpp Normal file
View 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);
}
};

78
src/api/api_poly.cpp Normal file
View file

@ -0,0 +1,78 @@
/*++
Copyright (c) 2012 Microsoft Corporation
Module Name:
api_poly.cpp
Abstract:
External API for polynomial package
Author:
Leonardo de Moura (leonardo) 2012-10-18.
Revision History:
--*/
#include"z3.h"
#include"z3_internal.h"
#include"api_context.h"
#include"api_poly.h"
#include"api_util.h"
#include"api_log_macros.h"
Z3_polynomial_manager Z3_mk_polynomial_manager(Z3_context c) {
Z3_TRY;
LOG_Z3_mk_polynomial_manager(c);
RESET_ERROR_CODE();
_Z3_polynomial_manager * m = alloc(_Z3_polynomial_manager);
RETURN_Z3(of_poly_manager(m));
Z3_CATCH_RETURN(0);
}
void Z3_del_polynomial_manager(Z3_context c, Z3_polynomial_manager m) {
Z3_TRY;
LOG_Z3_del_polynomial_manager(c, m);
RESET_ERROR_CODE();
dealloc(to_poly_manager(m));
Z3_CATCH;
}
Z3_polynomial Z3_mk_zero_polynomial(Z3_context c, Z3_polynomial_manager m) {
Z3_TRY;
LOG_Z3_mk_zero_polynomial(c, m);
RESET_ERROR_CODE();
polynomial::polynomial * r = to_poly_manager(m)->m_manager.mk_zero();
to_poly_manager(m)->m_result = r;
RETURN_Z3(of_poly(r));
Z3_CATCH_RETURN(0);
}
void Z3_polynomial_inc_ref(Z3_context c, Z3_polynomial_manager m, Z3_polynomial p) {
Z3_TRY;
LOG_Z3_polynomial_inc_ref(c, m, p);
RESET_ERROR_CODE();
to_poly_manager(m)->m_manager.inc_ref(to_poly(p));
Z3_CATCH;
}
void Z3_polynomial_dec_ref(Z3_context c, Z3_polynomial_manager m, Z3_polynomial p) {
Z3_TRY;
LOG_Z3_polynomial_inc_ref(c, m, p);
RESET_ERROR_CODE();
to_poly_manager(m)->m_manager.dec_ref(to_poly(p));
Z3_CATCH;
}
Z3_string Z3_polynomial_to_string(Z3_context c, Z3_polynomial_manager m, Z3_polynomial p) {
Z3_TRY;
LOG_Z3_polynomial_to_string(c, m, p);
RESET_ERROR_CODE();
std::ostringstream buffer;
to_poly_manager(m)->m_manager.display(buffer, to_poly(p));
return mk_c(c)->mk_external_string(buffer.str());
Z3_CATCH_RETURN("");
}

40
src/api/api_poly.h Normal file
View file

@ -0,0 +1,40 @@
/*++
Copyright (c) 2012 Microsoft Corporation
Module Name:
api_poly.h
Abstract:
External API for polynomial package
Author:
Leonardo de Moura (leonardo) 2012-10-18.
Revision History:
--*/
#ifndef _API_POLY_H_
#define _API_POLY_H_
#include"polynomial.h"
struct _Z3_polynomial_manager {
unsynch_mpz_manager m_num_manager;
polynomial::manager m_manager;
polynomial_ref m_result;
_Z3_polynomial_manager():
m_manager(m_num_manager),
m_result(m_manager) {
}
};
inline _Z3_polynomial_manager * to_poly_manager(Z3_polynomial_manager m) { return reinterpret_cast<_Z3_polynomial_manager*>(m); }
inline Z3_polynomial_manager of_poly_manager(_Z3_polynomial_manager * m) { return reinterpret_cast<Z3_polynomial_manager>(m); }
inline polynomial::polynomial * to_poly(Z3_polynomial p) { return reinterpret_cast<polynomial::polynomial*>(p); }
inline Z3_polynomial of_poly(polynomial::polynomial * p) { return reinterpret_cast<Z3_polynomial>(p); }
#endif

511
src/api/api_quant.cpp Normal file
View 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));
}
};

323
src/api/api_solver.cpp Normal file
View file

@ -0,0 +1,323 @@
/*++
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"
#include"default_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
src/api/api_solver.h Normal file
View 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
src/api/api_solver_old.cpp Normal file
View 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
src/api/api_stats.cpp Normal file
View 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
src/api/api_stats.h Normal file
View 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
src/api/api_tactic.cpp Normal file
View 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
src/api/api_tactic.h Normal file
View 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
src/api/api_user_theory.cpp Normal file
View 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);
}
};

150
src/api/api_util.h Normal file
View file

@ -0,0 +1,150 @@
/*++
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"
#include"ast.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

View file

@ -0,0 +1,494 @@
/*++
Copyright (c) 2007 Microsoft Corporation
Module Name:
ast_pattern_match.cpp
Abstract:
Search for opportune pattern matching utilities.
Author:
Nikolaj Bjorner (nbjorner) 2007-04-10
Leonardo (leonardo)
Notes:
instead of the brute force enumeration of permutations
we can add an instruction 'gate' which copies the ast
into a register and creates another register with the same
term. Matching against a 'gate' is a noop, apart from clearing
the ast in the register. Then on backtracking we know how many
terms were matched from the permutation. It does not make sense
to enumerate all combinations of terms that were not considered, so
skip these.
Also, compilation should re-order terms to fail fast.
--*/
#include"ast.h"
#include"expr_pattern_match.h"
#include"smtparser.h"
#include"for_each_ast.h"
#include"ast_ll_pp.h"
#include"ast_pp.h"
expr_pattern_match::expr_pattern_match(ast_manager & manager):
m_manager(manager), m_precompiled(manager) {
}
expr_pattern_match::~expr_pattern_match() {
}
bool
expr_pattern_match::match_quantifier(quantifier* qf, app_ref_vector& patterns, unsigned& weight) {
if (m_regs.empty()) {
// HACK: the code crashes if database is empty.
return false;
}
m_regs[0] = qf->get_expr();
for (unsigned i = 0; i < m_precompiled.size(); ++i) {
quantifier* qf2 = m_precompiled[i].get();
if (qf2->is_forall() != qf->is_forall()) {
continue;
}
if (qf2->get_num_decls() != qf->get_num_decls()) {
continue;
}
subst s;
if (match(qf->get_expr(), m_first_instrs[i], s)) {
for (unsigned j = 0; j < qf2->get_num_patterns(); ++j) {
app* p = static_cast<app*>(qf2->get_pattern(j));
expr_ref p_result(m_manager);
instantiate(p, qf->get_num_decls(), s, p_result);
patterns.push_back(to_app(p_result.get()));
}
weight = qf2->get_weight();
return true;
}
}
return false;
}
void
expr_pattern_match::instantiate(expr* a, unsigned num_bound, subst& s, expr_ref& result) {
bound b;
for (unsigned i = 0; i < num_bound; ++i) {
b.insert(m_bound_dom[i], m_bound_rng[i]);
}
inst_proc proc(m_manager, s, b, m_regs);
for_each_ast(proc, a);
expr* v = 0;
proc.m_memoize.find(a, v);
SASSERT(v);
result = v;
}
void
expr_pattern_match::compile(expr* q)
{
SASSERT(q->get_kind() == AST_QUANTIFIER);
quantifier* qf = to_quantifier(q);
unsigned ip = m_instrs.size();
m_first_instrs.push_back(ip);
m_precompiled.push_back(qf);
instr instr(BACKTRACK);
unsigned_vector regs;
ptr_vector<expr> pats;
unsigned max_reg = 1;
subst s;
pats.push_back(qf->get_expr());
regs.push_back(0);
unsigned num_bound = 0;
obj_map<var, unsigned> bound;
while (!pats.empty()) {
unsigned reg = regs.back();
expr* pat = pats.back();
regs.pop_back();
pats.pop_back();
instr.m_pat = pat;
instr.m_next = m_instrs.size()+1;
instr.m_reg = reg;
instr.m_offset = max_reg;
switch(pat->get_kind()) {
case AST_VAR: {
var* b = to_var(pat);
if (bound.find(b, instr.m_num_bound)) {
instr.m_kind = CHECK_BOUND;
}
else {
instr.m_kind = SET_BOUND;
instr.m_num_bound = num_bound;
bound.insert(b, num_bound);
++num_bound;
}
break;
}
case AST_APP: {
unsigned r = 0;
app* app = to_app(pat);
func_decl* d = app->get_decl();
for (unsigned i = 0; i < app->get_num_args(); ++i) {
regs.push_back(max_reg);
pats.push_back(app->get_arg(i));
++max_reg;
}
if (is_var(d)) {
if (s.find(d, r)) {
instr.m_kind = CHECK_VAR;
instr.m_other_reg = r;
}
else {
instr.m_kind = SET_VAR;
s.insert(d, reg);
}
}
else {
if (d->is_associative() && d->is_commutative()) {
instr.m_kind = BIND_AC;
}
else if (d->is_commutative()) {
SASSERT(app->get_num_args() == 2);
instr.m_kind = BIND_C;
}
else {
instr.m_kind = BIND;
}
}
break;
}
default:
instr.m_kind = CHECK_TERM;
break;
}
m_instrs.push_back(instr);
}
if (m_regs.size() <= max_reg) {
m_regs.resize(max_reg+1, 0);
}
if (m_bound_dom.size() <= num_bound) {
m_bound_dom.resize(num_bound+1, 0);
m_bound_rng.resize(num_bound+1, 0);
}
instr.m_kind = YIELD;
m_instrs.push_back(instr);
}
bool
expr_pattern_match::match(expr* a, unsigned init, subst& s)
{
svector<instr> bstack;
instr pc = m_instrs[init];
while (true) {
bool ok = false;
switch(pc.m_kind) {
case YIELD:
// substitution s contains registers with matching declarations.
return true;
case CHECK_TERM:
TRACE("expr_pattern_match", display(tout, pc);
ast_pp(tout, m_regs[pc.m_reg], m_manager) << "\n";);
ok = (pc.m_pat == m_regs[pc.m_reg]);
break;
case SET_VAR:
case CHECK_VAR: {
TRACE("expr_pattern_match", display(tout, pc);
ast_pp(tout, m_regs[pc.m_reg], m_manager) << "\n";);
app* app1 = to_app(pc.m_pat);
a = m_regs[pc.m_reg];
if (a->get_kind() != AST_APP) {
break;
}
app* app2 = to_app(a);
if (app1->get_num_args() != app2->get_num_args()) {
break;
}
if (pc.m_kind == CHECK_VAR &&
to_app(m_regs[pc.m_reg])->get_decl() !=
to_app(m_regs[pc.m_other_reg])->get_decl()) {
break;
}
for (unsigned i = 0; i < app2->get_num_args(); ++i) {
m_regs[pc.m_offset + i] = app2->get_arg(i);
}
if (pc.m_kind == SET_VAR) {
s.insert(app1->get_decl(), pc.m_reg);
}
ok = true;
break;
}
case SET_BOUND: {
TRACE("expr_pattern_match", display(tout, pc);
ast_pp(tout, m_regs[pc.m_reg], m_manager) << "\n";);
a = m_regs[pc.m_reg];
if (a->get_kind() != AST_VAR) {
break;
}
ok = true;
var* var_a = to_var(a);
var* var_p = to_var(pc.m_pat);
// check that the mapping of bound variables remains a bijection.
for (unsigned i = 0; ok && i < pc.m_num_bound; ++i) {
ok = (a != m_bound_rng[i]);
}
if (!ok) {
break;
}
m_bound_dom[pc.m_num_bound] = var_p;
m_bound_rng[pc.m_num_bound] = var_a;
break;
}
case CHECK_BOUND:
TRACE("expr_pattern_match",
tout
<< "check bound "
<< pc.m_num_bound << " " << pc.m_reg;
);
ok = m_bound_rng[pc.m_num_bound] == m_regs[pc.m_reg];
break;
case BIND:
case BIND_AC:
case BIND_C: {
TRACE("expr_pattern_match", display(tout, pc);
tout << mk_pp(m_regs[pc.m_reg],m_manager) << "\n";);
app* app1 = to_app(pc.m_pat);
a = m_regs[pc.m_reg];
if (a->get_kind() != AST_APP) {
break;
}
app* app2 = to_app(a);
if (app1->get_num_args() != app2->get_num_args()) {
break;
}
if (!match_decl(app1->get_decl(), app2->get_decl())) {
break;
}
switch(pc.m_kind) {
case BIND:
for (unsigned i = 0; i < app2->get_num_args(); ++i) {
m_regs[pc.m_offset + i] = app2->get_arg(i);
}
ok = true;
break; // process the next instruction.
case BIND_AC:
// push CHOOSE_AC on the backtracking stack.
bstack.push_back(instr(CHOOSE_AC, pc.m_offset, pc.m_next, app2, 1));
break;
case BIND_C:
// push CHOOSE_C on the backtracking stack.
ok = true;
m_regs[pc.m_offset] = app2->get_arg(0);
m_regs[pc.m_offset+1] = app2->get_arg(1);
bstack.push_back(instr(CHOOSE_C, pc.m_offset, pc.m_next, app2, 2));
break;
default:
break;
}
break;
}
case CHOOSE_C:
ok = true;
SASSERT (pc.m_count == 2);
m_regs[pc.m_offset+1] = pc.m_app->get_arg(0);
m_regs[pc.m_offset] = pc.m_app->get_arg(1);
break;
case CHOOSE_AC: {
ok = true;
app* app2 = pc.m_app;
for (unsigned i = 0; i < app2->get_num_args(); ++i) {
m_regs[pc.m_offset + i] = app2->get_arg(i);
}
// generate the k'th permutation.
unsigned k = pc.m_count;
unsigned fac = 1;
unsigned num_args = pc.m_app->get_num_args();
for (unsigned j = 2; j <= num_args; ++j) {
fac *= (j-1);
SASSERT(((k /fac) % j) + 1 <= j);
std::swap(m_regs[pc.m_offset + j - 1], m_regs[pc.m_offset + j - ((k / fac) % j) - 1]);
}
if (k < fac*num_args) {
bstack.push_back(instr(CHOOSE_AC, pc.m_offset, pc.m_next, app2, k+1));
}
TRACE("expr_pattern_match",
{
tout << "fac: " << fac << " num_args:" << num_args << " k:" << k << "\n";
for (unsigned i = 0; i < num_args; ++i) {
ast_pp(tout, m_regs[pc.m_offset + i], m_manager);
tout << " ";
}
tout << "\n";
});
break;
}
case BACKTRACK:
if (bstack.empty()) {
return false;
}
pc = bstack.back();
bstack.pop_back();
continue; // with the loop.
}
if (ok) {
pc = m_instrs[pc.m_next];
}
else {
TRACE("expr_pattern_match", tout << "backtrack\n";);
pc = m_instrs[0];
}
}
}
bool
expr_pattern_match::match_decl(func_decl const * pat, func_decl const * d) const {
if (pat == d) {
return true;
}
if (pat->get_arity() != d->get_arity()) {
return false;
}
// match families
if (pat->get_family_id() == null_family_id) {
return false;
}
if (d->get_family_id() != pat->get_family_id()) {
return false;
}
if (d->get_decl_kind() != pat->get_decl_kind()) {
return false;
}
if (d->get_num_parameters() != pat->get_num_parameters()) {
return false;
}
for (unsigned i = 0; i < d->get_num_parameters(); ++i) {
if (!(d->get_parameter(i) == pat->get_parameter(i))) {
return false;
}
}
return true;
}
bool
expr_pattern_match::is_var(func_decl* d) {
const char* s = d->get_name().bare_str();
return s && *s == '?';
}
void
expr_pattern_match::initialize(char const * spec_string) {
if (!m_instrs.empty()) {
return;
}
m_instrs.push_back(instr(BACKTRACK));
smtlib::parser* parser = smtlib::parser::create(m_manager);
parser->initialize_smtlib();
if (!parser->parse_string(spec_string)) {
UNREACHABLE();
}
smtlib::benchmark* bench = parser->get_benchmark();
smtlib::theory::expr_iterator it = bench->begin_formulas();
smtlib::theory::expr_iterator end = bench->end_formulas();
for (; it != end; ++it) {
compile(*it);
}
dealloc(parser);
TRACE("expr_pattern_match", display(tout); );
}
void
expr_pattern_match::display(std::ostream& out) const {
for (unsigned i = 0; i < m_instrs.size(); ++i) {
display(out, m_instrs[i]);
}
}
void
expr_pattern_match::display(std::ostream& out, instr const& pc) const {
switch(pc.m_kind) {
case BACKTRACK:
out << "backtrack\n";
break;
case BIND:
out << "bind ";
ast_pp(out, to_app(pc.m_pat)->get_decl(), m_manager) << " ";
ast_pp(out, pc.m_pat, m_manager) << "\n";
out << "next: " << pc.m_next << "\n";
out << "offset: " << pc.m_offset << "\n";
out << "reg: " << pc.m_reg << "\n";
break;
case BIND_AC:
out << "bind_ac ";
ast_pp(out, to_app(pc.m_pat)->get_decl(), m_manager) << " ";
ast_pp(out, pc.m_pat, m_manager) << "\n";
out << "next: " << pc.m_next << "\n";
out << "offset: " << pc.m_offset << "\n";
out << "reg: " << pc.m_reg << "\n";
break;
case BIND_C:
out << "bind_c ";
ast_pp(out, to_app(pc.m_pat)->get_decl(), m_manager) << " ";
ast_pp(out, pc.m_pat, m_manager) << "\n";
out << "next: " << pc.m_next << "\n";
out << "offset: " << pc.m_offset << "\n";
out << "reg: " << pc.m_reg << "\n";
break;
case CHOOSE_AC:
out << "choose_ac\n";
out << "next: " << pc.m_next << "\n";
out << "count: " << pc.m_count << "\n";
break;
case CHOOSE_C:
out << "choose_c\n";
out << "next: " << pc.m_next << "\n";
//out << "reg: " << pc.m_reg << "\n";
break;
case CHECK_VAR:
out << "check_var ";
ast_pp(out, pc.m_pat, m_manager) << "\n";
out << "next: " << pc.m_next << "\n";
out << "reg: " << pc.m_reg << "\n";
out << "other_reg: " << pc.m_other_reg << "\n";
break;
case CHECK_TERM:
out << "check ";
ast_pp(out, pc.m_pat, m_manager) << "\n";
out << "next: " << pc.m_next << "\n";
out << "reg: " << pc.m_reg << "\n";
break;
case YIELD:
out << "yield\n";
break;
case SET_VAR:
out << "set_var ";
ast_pp(out, pc.m_pat, m_manager) << "\n";
out << "next: " << pc.m_next << "\n";
break;
default:
break;
} }
// TBD: fix type overloading.
// TBD: bound number of permutations.
// TBD: forward pruning checks.

View file

@ -0,0 +1,149 @@
/*++
Copyright (c) 2007 Microsoft Corporation
Module Name:
expr_pattern_match.h
Abstract:
Search for opportune pattern matching utilities.
Author:
Nikolaj Bjorner (nbjorner) 2007-04-10
Leonardo (leonardo)
Notes:
--*/
#ifndef _EXPR_PATTERN_MATCH_H_
#define _EXPR_PATTERN_MATCH_H_
#include"ast.h"
#include"map.h"
#include"front_end_params.h"
#include"pattern_inference.h"
class expr_pattern_match : public pattern_database {
enum instr_kind {
BACKTRACK,
BIND,
BIND_AC,
BIND_C,
CHOOSE_AC,
CHOOSE_C,
SET_VAR,
CHECK_VAR,
CHECK_TERM,
SET_BOUND,
CHECK_BOUND,
YIELD,
};
struct instr {
instr(instr_kind k) : m_kind(k) {}
instr(instr_kind k, unsigned o, unsigned next, app* app, unsigned count):
m_kind(k), m_offset(o), m_next(next), m_app(app), m_count(count) {}
instr_kind m_kind;
unsigned m_offset;
unsigned m_next;
app* m_app;
expr* m_pat;
unsigned m_reg;
unsigned m_other_reg;
unsigned m_count;
unsigned m_num_bound;
};
typedef obj_map<func_decl, unsigned> subst;
typedef obj_map<var, var*> bound;
struct inst_proc {
ast_manager& m_manager;
expr_ref_vector m_pinned;
subst& m_subst;
bound& m_bound;
obj_map<expr, expr*> m_memoize;
ptr_vector<expr>& m_regs;
inst_proc(ast_manager& m, subst& s, bound& b, ptr_vector<expr>& regs) :
m_manager(m), m_pinned(m), m_subst(s), m_bound(b), m_regs(regs) {}
void operator()(ast* a) {
}
void operator()(expr* a) {
m_memoize.insert(a, a);
}
void operator()(var* v) {
var* b = 0;
if (m_bound.find(v, b)) {
m_memoize.insert(v, b);
}
else {
UNREACHABLE();
}
}
void operator()(app * n) {
unsigned r;
ptr_vector<expr> args;
unsigned num_args = n->get_num_args();
func_decl * decl = n->get_decl();
expr* result;
if (m_subst.find(decl, r)) {
decl = to_app(m_regs[r])->get_decl();
}
for (unsigned i = 0; i < num_args; ++i) {
expr* arg = 0;
if (m_memoize.find(n->get_arg(i), arg)) {
SASSERT(arg);
args.push_back(arg);
}
else {
UNREACHABLE();
}
}
if (m_manager.is_pattern(n)) {
result = m_manager.mk_pattern(num_args, reinterpret_cast<app**>(args.c_ptr()));
}
else {
result = m_manager.mk_app(decl, num_args, args.c_ptr());
}
m_pinned.push_back(result);
m_memoize.insert(n, result);
return;
}
};
ast_manager & m_manager;
quantifier_ref_vector m_precompiled;
unsigned_vector m_first_instrs;
svector<instr> m_instrs;
ptr_vector<expr> m_regs;
ptr_vector<var> m_bound_dom;
ptr_vector<var> m_bound_rng;
public:
expr_pattern_match(ast_manager & manager);
~expr_pattern_match();
virtual bool match_quantifier(quantifier * qf, app_ref_vector & patterns, unsigned & weight);
virtual void initialize(char const * database);
void display(std::ostream& out) const;
private:
void instantiate(expr* a, unsigned num_bound, subst& s, expr_ref& result);
void compile(expr* q);
bool match(expr* a, unsigned init, subst& s);
bool match_decl(func_decl const * pat, func_decl const * d) const;
bool is_var(func_decl* d);
void display(std::ostream& out, instr const& pc) const;
};
#endif

252
src/api/smtlib.cpp Normal file
View file

@ -0,0 +1,252 @@
#include"smtlib.h"
#include"ast_pp.h"
#include"ast_smt2_pp.h"
#ifdef _WINDOWS
#ifdef ARRAYSIZE
#undef ARRAYSIZE
#endif
#include <windows.h>
#include <strsafe.h>
#endif
#include <iostream>
using namespace smtlib;
// --------------------------------------------------------------------------
// symtable
symtable::~symtable() {
reset();
}
void symtable::reset() {
svector<ptr_vector<func_decl>*> range;
m_ids.get_range(range);
for (unsigned i = 0; i < range.size(); ++i) {
ptr_vector<func_decl> const & v = *range[i];
for (unsigned j = 0; j < v.size(); ++j) {
m_manager.dec_ref(v[j]);
}
dealloc(range[i]);
}
m_ids.reset();
ptr_vector<sort> sorts;
m_sorts1.get_range(sorts);
for (unsigned i = 0; i < sorts.size(); ++i) {
m_manager.dec_ref(sorts[i]);
}
m_sorts1.reset();
ptr_vector<sort_builder> sort_builders;
m_sorts.get_range(sort_builders);
for (unsigned i = 0; i < sort_builders.size(); ++i) {
dealloc(sort_builders[i]);
}
m_sorts.reset();
}
void symtable::insert(symbol s, func_decl * d) {
ptr_vector<func_decl>* decls = 0;
m_manager.inc_ref(d);
if (!m_ids.find(s, decls)) {
SASSERT(!decls);
decls = alloc(ptr_vector<func_decl>);
decls->push_back(d);
m_ids.insert(s, decls);
}
else {
SASSERT(decls);
if ((*decls)[0] != d) {
decls->push_back(d);
}
else {
m_manager.dec_ref(d);
}
}
}
bool symtable::find1(symbol s, func_decl*& d) {
ptr_vector<func_decl>* decls = 0;
if (!m_ids.find(s, decls)) {
SASSERT(!decls);
return false;
}
SASSERT(decls && !decls->empty());
d = (*decls)[0];
return true;
}
bool symtable::find_overload(symbol s, ptr_vector<sort> const & dom, func_decl * & d) {
ptr_vector<func_decl>* decls = 0;
d = 0;
if (!m_ids.find(s, decls)) {
SASSERT(!decls);
return false;
}
SASSERT(decls);
for (unsigned i = 0; i < decls->size(); ++i) {
func_decl* decl = (*decls)[i];
if (decl->is_associative() && decl->get_arity() > 0) {
for (unsigned j = 0; j < dom.size(); ++j) {
if (dom[j] != decl->get_domain(0)) {
goto try_next;
}
}
d = decl;
return true;
}
if (decl->get_arity() != dom.size()) {
goto try_next;
}
for (unsigned j = 0; j < decl->get_arity(); ++j) {
if (decl->get_domain(j) != dom[j]) {
goto try_next;
}
}
d = decl;
return true;
try_next:
if (decl->get_family_id() == m_manager.get_basic_family_id() && decl->get_decl_kind() == OP_DISTINCT) {
// we skip type checking for 'distinct'
d = decl;
return true;
}
}
return false;
}
// Store in result the func_decl that are not attached to any family id.
// That is, the uninterpreted constants and function declarations.
void symtable::get_func_decls(ptr_vector<func_decl> & result) const {
svector<ptr_vector<func_decl>*> tmp;
m_ids.get_range(tmp);
svector<ptr_vector<func_decl>*>::const_iterator it = tmp.begin();
svector<ptr_vector<func_decl>*>::const_iterator end = tmp.end();
for (; it != end; ++it) {
ptr_vector<func_decl> * curr = *it;
if (curr) {
ptr_vector<func_decl>::const_iterator it2 = curr->begin();
ptr_vector<func_decl>::const_iterator end2 = curr->end();
for (; it2 != end2; ++it2) {
func_decl * d = *it2;
if (d && d->get_family_id() == null_family_id) {
result.push_back(d);
}
}
}
}
}
void symtable::insert(symbol s, sort_builder* sb) {
m_sorts.insert(s, sb);
}
bool symtable::lookup(symbol s, sort_builder*& sb) {
return m_sorts.find(s, sb);
}
void symtable::push_sort(symbol name, sort* srt) {
m_sorts.begin_scope();
sort_builder* sb = alloc(basic_sort_builder,srt);
m_sorts.insert(name, sb);
m_sorts_trail.push_back(sb);
}
void symtable::pop_sorts(unsigned num_sorts) {
while (num_sorts > 0) {
dealloc(m_sorts_trail.back());
m_sorts_trail.pop_back();
m_sorts.end_scope();
}
}
void symtable::get_sorts(ptr_vector<sort>& result) const {
vector<sort*,false> tmp;
m_sorts1.get_range(tmp);
for (unsigned i = 0; i < tmp.size(); ++i) {
if (tmp[i]->get_family_id() == null_family_id) {
result.push_back(tmp[i]);
}
}
}
// --------------------------------------------------------------------------
// theory
func_decl * theory::declare_func(symbol const & id, sort_ref_buffer & domain, sort * range,
bool is_assoc, bool is_comm, bool is_inj) {
func_decl * decl = m_ast_manager.mk_func_decl(id, domain.size(), domain.c_ptr(), range,
is_assoc, is_comm, is_inj);
m_symtable.insert(id, decl);
m_asts.push_back(decl);
return decl;
}
sort * theory::declare_sort(symbol const & id) {
sort * decl = m_ast_manager.mk_sort(id);
m_symtable.insert(id, decl);
m_asts.push_back(decl);
return decl;
}
bool theory::get_func_decl(symbol id, func_decl * & decl) {
return m_symtable.find1(id, decl);
}
bool theory::get_sort(symbol id, sort* & s) {
return m_symtable.find(id, s);
}
bool theory::get_const(symbol id, expr * & term) {
func_decl* decl = 0;
if (!get_func_decl(id,decl)) {
return false;
}
if (decl->get_arity() != 0) {
return false;
}
term = m_ast_manager.mk_const(decl);
m_asts.push_back(term);
return true;
}
void benchmark::display_as_smt2(std::ostream & out) const {
if (m_logic != symbol::null)
out << "(set-logic " << m_logic << ")\n";
out << "(set-info :smt-lib-version 2.0)\n";
out << "(set-info :status ";
switch (m_status) {
case SAT: out << "sat"; break;
case UNSAT: out << "unsat"; break;
default: out << "unknown"; break;
}
out << ")\n";
#if 0
ast_manager & m = m_ast_manager;
ptr_vector<func_decl> decls;
m_symtable.get_func_decls(decls);
ptr_vector<func_decl>::const_iterator it = decls.begin();
ptr_vector<func_decl>::const_iterator end = decls.end();
for (; it != end; ++it) {
func_decl * f = *it;
out << "(declare-fun " << f->get_name() << " (";
for (unsigned i = 0; i < f->get_arity(); i++) {
if (i > 0) out << " ";
out << mk_ismt2_pp(f->get_domain(i), m);
}
out << ") " << mk_ismt2_pp(f->get_range(), m);
out << ")\n";
}
#endif
}

232
src/api/smtlib.h Normal file
View file

@ -0,0 +1,232 @@
/*++
Copyright (c) 2006 Microsoft Corporation
Module Name:
smtlib.h
Abstract:
SMT library utilities
Author:
Nikolaj Bjorner (nbjorner) 2006-09-29
Revision History:
--*/
#ifndef _SMTLIB_H_
#define _SMTLIB_H_
#include "ast.h"
#include "symbol_table.h"
#include "map.h"
#include "arith_decl_plugin.h"
namespace smtlib {
class sort_builder {
public:
virtual ~sort_builder() {}
virtual bool apply(unsigned num_params, parameter const* params, sort_ref& result) = 0;
virtual char const* error_message() { return ""; }
};
class basic_sort_builder : public sort_builder {
sort* m_sort;
public:
basic_sort_builder(sort* s) : m_sort(s) {}
virtual bool apply(unsigned np, parameter const*, sort_ref& result) {
result = m_sort;
return m_sort && np != 0;
}
};
class symtable {
ast_manager& m_manager;
symbol_table<sort*> m_sorts1;
symbol_table<sort_builder*> m_sorts;
ptr_vector<sort_builder> m_sorts_trail;
symbol_table<ptr_vector<func_decl>* > m_ids;
public:
symtable(ast_manager& m): m_manager(m) {}
~symtable();
void reset();
void insert(symbol s, func_decl * d);
bool find(symbol s, ptr_vector<func_decl> * & decls) {
return m_ids.find(s, decls);
}
bool find1(symbol s, func_decl * & d);
bool find_overload(symbol s, ptr_vector<sort> const & dom, func_decl * & d);
void insert(symbol s, sort * d) {
sort * d2;
if (m_sorts1.find(s, d2)) {
m_manager.dec_ref(d2);
}
m_manager.inc_ref(d);
m_sorts1.insert(s, d);
}
bool find(symbol s, sort * & d) {
return m_sorts1.find(s, d);
}
void insert(symbol s, sort_builder* sb);
bool lookup(symbol s, sort_builder*& sb);
void push_sort(symbol s, sort*);
void pop_sorts(unsigned num_sorts);
void get_func_decls(ptr_vector<func_decl> & result) const;
void get_sorts(ptr_vector<sort>& result) const;
};
class theory {
public:
typedef ptr_vector<expr>::const_iterator expr_iterator;
theory(ast_manager & ast_manager, symbol const& name):
m_name(name),
m_ast_manager(ast_manager),
m_symtable(ast_manager),
m_asts(ast_manager)
{}
virtual ~theory() {}
symtable * get_symtable() { return &m_symtable; }
void insert(sort * s) { m_symtable.insert(s->get_name(), s); }
void insert(func_decl * c) { m_symtable.insert(c->get_name(), c); }
func_decl * declare_func(symbol const & id, sort_ref_buffer & domain, sort * range,
bool is_assoc, bool is_comm, bool is_inj);
sort * declare_sort(symbol const & id);
void add_axiom(expr * axiom) {
m_asts.push_back(axiom);
m_axioms.push_back(axiom);
}
expr_iterator begin_axioms() const {
return m_axioms.begin();
}
unsigned get_num_axioms() const {
return m_axioms.size();
}
expr * const * get_axioms() const {
return m_axioms.c_ptr();
}
expr_iterator end_axioms() const {
return m_axioms.end();
}
void add_assumption(expr * axiom) {
m_asts.push_back(axiom);
m_assumptions.push_back(axiom);
}
unsigned get_num_assumptions() const {
return m_assumptions.size();
}
expr * const * get_assumptions() const {
return m_assumptions.c_ptr();
}
bool get_func_decl(symbol, func_decl*&);
bool get_sort(symbol, sort*&);
bool get_const(symbol, expr*&);
void set_name(symbol const& name) { m_name = name; }
symbol const get_name() const { return m_name; }
protected:
symbol m_name;
ast_manager& m_ast_manager;
ptr_vector<expr> m_axioms;
ptr_vector<expr> m_assumptions;
symtable m_symtable;
ast_ref_vector m_asts;
private:
theory& operator=(theory const&);
theory(theory const&);
};
class benchmark : public theory {
public:
enum status {
UNKNOWN,
SAT,
UNSAT
};
benchmark(ast_manager & ast_manager, symbol const & name) :
theory(ast_manager, name),
m_status(UNKNOWN) {}
virtual ~benchmark() {}
status get_status() const { return m_status; }
void set_status(status status) { m_status = status; }
symbol get_logic() const {
if (m_logic == symbol::null) {
return symbol("ALL");
}
return m_logic;
}
void set_logic(symbol const & s) { m_logic = s; }
unsigned get_num_formulas() const {
return m_formulas.size();
}
expr_iterator begin_formulas() const {
return m_formulas.begin();
}
expr_iterator end_formulas() const {
return m_formulas.end();
}
void add_formula(expr * formula) {
m_asts.push_back(formula);
m_formulas.push_back(formula);
}
void display_as_smt2(std::ostream & out) const;
private:
status m_status;
symbol m_logic;
ptr_vector<expr> m_formulas;
};
};
#endif

116
src/api/smtlib_solver.cpp Normal file
View file

@ -0,0 +1,116 @@
/*++
Copyright (c) 2006 Microsoft Corporation
Module Name:
smtlib_solver.cpp
Abstract:
SMT based solver.
Author:
Nikolaj Bjorner (nbjorner) 2006-11-3.
Revision History:
--*/
#include"smtparser.h"
#include"smtlib_solver.h"
#include"warning.h"
#include"ast_pp.h"
#include"ast_ll_pp.h"
#include"well_sorted.h"
#include"spc_prover.h"
#include"model.h"
#include"model_v2_pp.h"
#include"solver.h"
#include"smt_strategic_solver.h"
#include"cmd_context.h"
namespace smtlib {
solver::solver(front_end_params & params):
m_ast_manager(params.m_proof_mode, params.m_trace_stream),
m_params(params),
m_ctx(0),
m_parser(parser::create(m_ast_manager, params.m_ignore_user_patterns)),
m_error_code(0) {
m_parser->initialize_smtlib();
}
solver::~solver() {
if (m_ctx)
dealloc(m_ctx);
}
bool solver::solve_smt(char const * benchmark_file) {
IF_VERBOSE(100, verbose_stream() << "parsing...\n";);
if (!m_parser->parse_file(benchmark_file)) {
if (benchmark_file) {
warning_msg("could not parse file '%s'.", benchmark_file);
}
else {
warning_msg("could not parse input stream.");
}
m_error_code = ERR_PARSER;
return false;
}
benchmark * benchmark = m_parser->get_benchmark();
solve_benchmark(*benchmark);
return true;
}
bool solver::solve_smt_string(char const * benchmark_string) {
if (!m_parser->parse_string(benchmark_string)) {
warning_msg("could not parse string '%s'.", benchmark_string);
return false;
}
benchmark * benchmark = m_parser->get_benchmark();
solve_benchmark(*benchmark);
return true;
}
void solver::display_statistics() {
if (m_ctx)
m_ctx->display_statistics();
}
void solver::solve_benchmark(benchmark & benchmark) {
if (benchmark.get_num_formulas() == 0) {
// Hack: it seems SMT-LIB allow benchmarks without any :formula
benchmark.add_formula(m_ast_manager.mk_true());
}
m_ctx = alloc(cmd_context, m_params, true, &m_ast_manager, benchmark.get_logic());
m_ctx->set_solver(mk_smt_strategic_solver(*m_ctx));
theory::expr_iterator fit = benchmark.begin_formulas();
theory::expr_iterator fend = benchmark.end_formulas();
for (; fit != fend; ++fit)
solve_formula(benchmark, *fit);
}
void solver::solve_formula(benchmark const & benchmark, expr * f) {
IF_VERBOSE(100, verbose_stream() << "starting...\n";);
m_ctx->reset();
for (unsigned i = 0; i < benchmark.get_num_axioms(); i++)
m_ctx->assert_expr(benchmark.get_axioms()[i]);
m_ctx->assert_expr(f);
m_ctx->check_sat(benchmark.get_num_assumptions(), benchmark.get_assumptions());
check_sat_result * r = m_ctx->get_check_sat_result();
if (r != 0) {
proof * pr = r->get_proof();
if (pr != 0 && m_params.m_display_proof)
std::cout << mk_ll_pp(pr, m_ast_manager, false, false);
model_ref md;
if (r->status() != l_false) r->get_model(md);
if (md.get() != 0 && m_params.m_model) {
model_v2_pp(std::cout, *(md.get()), m_params.m_model_partial);
}
}
else {
m_error_code = ERR_UNKNOWN_RESULT;
}
}
};

48
src/api/smtlib_solver.h Normal file
View file

@ -0,0 +1,48 @@
/*++
Copyright (c) 2006 Microsoft Corporation
Module Name:
smtlib_solver.h
Abstract:
SMT based solver.
Author:
Nikolaj Bjorner (nbjorner) 2006-11-3.
Revision History:
--*/
#ifndef _SMTLIB_SOLVER_H_
#define _SMTLIB_SOLVER_H_
#include"smtparser.h"
#include"front_end_params.h"
#include"lbool.h"
class cmd_context;
namespace smtlib {
class solver {
ast_manager m_ast_manager;
front_end_params & m_params;
cmd_context * m_ctx;
scoped_ptr<parser> m_parser;
unsigned m_error_code;
public:
solver(front_end_params & params);
~solver();
bool solve_smt(char const * benchmark_file);
bool solve_smt_string(char const * benchmark_string);
void display_statistics();
unsigned get_error_code() const { return m_error_code; }
private:
void solve_benchmark(benchmark & benchmark);
void solve_formula(benchmark const & benchmark, expr * f);
};
};
#endif

5317
src/api/smtparser.cpp Normal file

File diff suppressed because it is too large Load diff

51
src/api/smtparser.h Normal file
View file

@ -0,0 +1,51 @@
/*++
Copyright (c) 2006 Microsoft Corporation
Module Name:
smtparser.h
Abstract:
SMT parsing utilities
Author:
Nikolaj Bjorner (nbjorner) 2006-09-25
Revision History:
--*/
#ifndef _SMT_PARSER_H_
#define _SMT_PARSER_H_
#include "ast.h"
#include "vector.h"
#include "smtlib.h"
#include "z3.h"
#include <iostream>
namespace smtlib {
class parser {
public:
static parser * create(ast_manager & ast_manager, bool ignore_user_patterns = false);
virtual ~parser() {}
virtual void add_builtin_op(char const *, family_id fid, decl_kind kind) = 0;
virtual void add_builtin_type(char const *, family_id fid, decl_kind kind) = 0;
virtual void initialize_smtlib() = 0;
virtual void set_error_stream(std::ostream& strm) = 0;
virtual bool parse_file(char const * path) = 0;
virtual bool parse_string(char const * string) = 0;
virtual bool parse_commands(Z3_context ctx, std::istream& is, std::ostream& os) = 0;
virtual benchmark * get_benchmark() = 0;
};
};
#endif

40
src/api/z3.h Normal file
View file

@ -0,0 +1,40 @@
/*++
Copyright (c) 2007 Microsoft Corporation
Module Name:
z3.h
Abstract:
Z3 API.
Author:
Nikolaj Bjorner (nbjorner)
Leonardo de Moura (leonardo) 2007-06-8
Notes:
--*/
#ifndef _Z3__H_
#define _Z3__H_
#include<stdio.h>
#include"z3_macros.h"
#include"z3_api.h"
#include"z3_internal_types.h"
#undef __in
#undef __out
#undef __inout
#undef __in_z
#undef __out_z
#undef __ecount
#undef __in_ecount
#undef __out_ecount
#undef __inout_ecount
#endif

7563
src/api/z3_api.h Normal file

File diff suppressed because it is too large Load diff

40
src/api/z3_internal.h Normal file
View file

@ -0,0 +1,40 @@
/*++
Copyright (c) 2012 Microsoft Corporation
Module Name:
z3_internal.h
Abstract:
Z3 internal API for C and Python.
It provides access to internal Z3 components.
It should only be used by advanced users.
We used it to build regression tests in Python.
Author:
Leonardo de Moura (leonardo) 2012-10-18
Notes:
--*/
#ifndef _Z3_INTERNAL_H_
#define _Z3_INTERNAL_H_
#include"z3_macros.h"
#include"z3_api.h"
#include"z3_internal_types.h"
#include"z3_poly.h"
#undef __in
#undef __out
#undef __inout
#undef __in_z
#undef __out_z
#undef __ecount
#undef __in_ecount
#undef __out_ecount
#undef __inout_ecount
#endif

View file

@ -0,0 +1,34 @@
/*++
Copyright (c) 2012 Microsoft Corporation
Module Name:
z3_internal_types.h
Abstract:
Z3 internal API type declarations.
Author:
Leonardo de Moura (leonardo) 2012-10-18
Notes:
--*/
#ifndef _Z3_INTERNAL_TYPES_H_
#define _Z3_INTERNAL_TYPES_H_
DEFINE_TYPE(Z3_polynomial_manager);
DEFINE_TYPE(Z3_polynomial);
DEFINE_TYPE(Z3_monomial);
/*
Definitions for update_api.py
def_Type('POLYNOMIAL_MANAGER', 'Z3_polynomial_manager', 'PolynomialManagerObj')
def_Type('POLYNOMIAL', 'Z3_polynomial', 'PolynomialObj')
def_Type('MONOMIAL', 'Z3_monomial', 'MonomialObj')
*/
#endif

70
src/api/z3_logger.h Normal file
View file

@ -0,0 +1,70 @@
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
z3_logger.h
Abstract:
Goodies for log generation
Author:
Leonardo de Moura (leonardo) 2011-09-22
Notes:
--*/
#include<iostream>
#include"symbol.h"
struct ll_escaped { char const * m_str; ll_escaped(char const * str):m_str(str) {} };
static std::ostream & operator<<(std::ostream & out, ll_escaped const & d) {
char const * s = d.m_str;
while (*s) {
char c = *s;
if (('0' <= c && c <= '9') || ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') ||
c == '~' || c == '!' || c == '@' || c == '#' || c == '$' || c == '%' || c == '^' || c == '&' ||
c == '*' || c == '-' || c == '_' || c == '+' || c == '.' || c == '?' || c == '/' || c == ' ' ||
c == '<' || c == '>') {
out << c;
}
else {
char str[4] = {'0', '0', '0', 0};
str[2] = '0' + (c % 10);
c /= 10;
str[1] = '0' + (c % 10);
c /= 10;
str[0] = '0' + c;
out << '\\' << str;
}
s++;
}
return out;
}
static void R() { *g_z3_log << "R\n"; g_z3_log->flush(); }
static void P(void * obj) { *g_z3_log << "P " << obj << "\n"; g_z3_log->flush(); }
static void I(__int64 i) { *g_z3_log << "I " << i << "\n"; g_z3_log->flush(); }
static void U(__uint64 u) { *g_z3_log << "U " << u << "\n"; g_z3_log->flush(); }
static void D(double d) { *g_z3_log << "D " << d << "\n"; g_z3_log->flush(); }
static void S(Z3_string str) { *g_z3_log << "S \"" << ll_escaped(str) << "\"\n"; g_z3_log->flush(); }
static void Sy(Z3_symbol sym) {
symbol s = symbol::mk_symbol_from_c_ptr(reinterpret_cast<void *>(sym));
if (s == symbol::null) {
*g_z3_log << "N\n";
}
else if (s.is_numerical()) {
*g_z3_log << "# " << s.get_num() << "\n";
}
else {
*g_z3_log << "$ |" << ll_escaped(s.bare_str()) << "|\n";
}
g_z3_log->flush();
}
static void Ap(unsigned sz) { *g_z3_log << "p " << sz << "\n"; g_z3_log->flush(); }
static void Au(unsigned sz) { *g_z3_log << "u " << sz << "\n"; g_z3_log->flush(); }
static void Asy(unsigned sz) { *g_z3_log << "s " << sz << "\n"; g_z3_log->flush(); }
static void C(unsigned id) { *g_z3_log << "C " << id << "\n"; g_z3_log->flush(); }
void _Z3_append_log(char const * msg) { *g_z3_log << "M \"" << ll_escaped(msg) << "\"\n"; g_z3_log->flush(); }

54
src/api/z3_macros.h Normal file
View file

@ -0,0 +1,54 @@
#ifndef __in
#define __in
#endif
#ifndef __out
#define __out
#endif
#ifndef __out_opt
#define __out_opt __out
#endif
#ifndef __ecount
#define __ecount(num_args)
#endif
#ifndef __in_ecount
#define __in_ecount(num_args) __in __ecount(num_args)
#endif
#ifndef __out_ecount
#define __out_ecount(num_args) __out __ecount(num_args)
#endif
#ifndef __inout_ecount
#define __inout_ecount(num_args) __in __out __ecount(num_args)
#endif
#ifndef __inout
#define __inout __in __out
#endif
#ifndef Z3_bool_opt
#define Z3_bool_opt Z3_bool
#endif
#ifndef Z3_API
#define Z3_API
#endif
#ifndef DEFINE_TYPE
#define DEFINE_TYPE(T) typedef struct _ ## T *T
#endif
#ifndef DEFINE_VOID
#define DEFINE_VOID(T) typedef void* T
#endif
#ifndef BEGIN_MLAPI_EXCLUDE
#define BEGIN_MLAPI_EXCLUDE
#endif
#ifndef END_MLAPI_EXCLUDE
#define END_MLAPI_EXCLUDE
#endif

72
src/api/z3_poly.h Normal file
View file

@ -0,0 +1,72 @@
/*++
Copyright (c) 2012 Microsoft Corporation
Module Name:
z3_poly.h
Abstract:
Z3 multivariate polynomial API.
Author:
Leonardo de Moura (leonardo) 2012-10-18
Notes:
--*/
#ifndef _Z3_POLY_H_
#define _Z3_POLY_H_
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
/**
\brief Create a new polynomial manager.
def_API('Z3_mk_polynomial_manager', POLYNOMIAL_MANAGER, (_in(CONTEXT),))
*/
Z3_polynomial_manager Z3_API Z3_mk_polynomial_manager(__in Z3_context c);
/**
\brief Delete the given polynomial manager.
def_API('Z3_del_polynomial_manager', VOID, (_in(CONTEXT), _in(POLYNOMIAL_MANAGER)))
*/
void Z3_API Z3_del_polynomial_manager(__in Z3_context c, __in Z3_polynomial_manager m);
/**
\brief Return the zero polynomial.
def_API('Z3_mk_zero_polynomial', POLYNOMIAL, (_in(CONTEXT), _in(POLYNOMIAL_MANAGER)))
*/
Z3_polynomial Z3_API Z3_mk_zero_polynomial(__in Z3_context c, __in Z3_polynomial_manager m);
/**
\brief Increment p's reference counter
def_API('Z3_polynomial_inc_ref', VOID, (_in(CONTEXT), _in(POLYNOMIAL_MANAGER), _in(POLYNOMIAL)))
*/
void Z3_API Z3_polynomial_inc_ref(__in Z3_context c, __in Z3_polynomial_manager m, __in Z3_polynomial p);
/**
\brief Decrement p's reference counter.
def_API('Z3_polynomial_dec_ref', VOID, (_in(CONTEXT), _in(POLYNOMIAL_MANAGER), _in(POLYNOMIAL)))
*/
void Z3_API Z3_polynomial_dec_ref(__in Z3_context c, __in Z3_polynomial_manager m, __in Z3_polynomial p);
/**
\brief Convert the given polynomial into a string.
def_API('Z3_polynomial_to_string', STRING, (_in(CONTEXT), _in(POLYNOMIAL_MANAGER), _in(POLYNOMIAL)))
*/
Z3_string Z3_API Z3_polynomial_to_string(__in Z3_context c, __in Z3_polynomial_manager m, __in Z3_polynomial p);
#ifdef __cplusplus
};
#endif // __cplusplus
#endif

80
src/api/z3_private.h Normal file
View file

@ -0,0 +1,80 @@
/*++
Copyright (c) 2007 Microsoft Corporation
Module Name:
z3_private.h
Abstract:
Z3 API.
Author:
Nikolaj Bjorner (nbjorner)
Leonardo de Moura (leonardo) 2007-06-8
Notes:
--*/
#include<iostream>
#include"rational.h"
#include"z3_macros.h"
#ifndef _Z3_PRIVATE__H_
#define _Z3_PRIVATE__H_
#ifndef CAMLIDL
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
#else
[pointer_default(ref)] interface Z3 {
#endif // CAMLIDL
Z3_bool Z3_API Z3_get_numeral_rational(__in Z3_context c, __in Z3_ast a, rational& r);
/**
\brief \mlh exec_smtlib2_string c str \endmlh
Parse the given string using the SMT-LIB2 parser and execute its commands.
It returns a formula comprising of the conjunction of assertions in the scope
(up to push/pop) at the end of the string.
The returned formula is also asserted to the logical context on return.
*/
Z3_ast Z3_API Z3_exec_smtlib2_string(__in Z3_context c,
__in Z3_string str,
__in unsigned num_sorts,
__in_ecount(num_sorts) Z3_symbol sort_names[],
__in_ecount(num_sorts) Z3_sort sorts[],
__in unsigned num_decls,
__in_ecount(num_decls) Z3_symbol decl_names[],
__in_ecount(num_decls) Z3_func_decl decls[]
);
/**
\brief Similar to #Z3_exec_smtlib2_string, but reads the commands from a file.
*/
Z3_ast Z3_API Z3_exec_smtlib2_file(__in Z3_context c,
__in Z3_string file_name,
__in unsigned num_sorts,
__in_ecount(num_sorts) Z3_symbol sort_names[],
__in_ecount(num_sorts) Z3_sort sorts[],
__in unsigned num_decls,
__in_ecount(num_decls) Z3_symbol decl_names[],
__in_ecount(num_decls) Z3_func_decl decls[]
);
#ifndef CAMLIDL
#ifdef __cplusplus
};
#endif // __cplusplus
#else
}
#endif // CAMLIDL
#endif

711
src/api/z3_replayer.cpp Normal file
View file

@ -0,0 +1,711 @@
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
z3_replayer.cpp
Abstract:
Interpreter for Z3 logs
Author:
Leonardo de Moura (leonardo) 2011-09-22
Notes:
--*/
#include"vector.h"
#include"map.h"
#include"z3_replayer.h"
#include"stream_buffer.h"
#include"symbol.h"
#include"trace.h"
void register_z3_replayer_cmds(z3_replayer & in);
void throw_invalid_reference() {
throw z3_replayer_exception("invalid argument reference");
}
struct z3_replayer::imp {
z3_replayer & m_owner;
std::istream & m_stream;
char m_curr; // current char;
int m_line; // line
svector<char> m_string;
symbol m_id;
__int64 m_int64;
__uint64 m_uint64;
double m_double;
size_t m_ptr;
size_t_map<void *> m_heap;
svector<z3_replayer_cmd> m_cmds;
enum value_kind { INT64, UINT64, DOUBLE, STRING, SYMBOL, OBJECT, UINT_ARRAY, SYMBOL_ARRAY, OBJECT_ARRAY };
struct value {
value_kind m_kind;
union {
__int64 m_int;
__uint64 m_uint;
double m_double;
char const * m_str;
void * m_obj;
};
value():m_kind(OBJECT), m_int(0) {}
value(void * obj):m_kind(OBJECT), m_obj(obj) {}
value(value_kind k, char const * str):m_kind(k), m_str(str) {}
value(value_kind k, __uint64 u):m_kind(k), m_uint(u) {}
value(value_kind k, __int64 i):m_kind(k), m_int(i) {}
value(value_kind k, double d):m_kind(k), m_double(d) {}
};
svector<value> m_args;
void * m_result;
vector<ptr_vector<void> > m_obj_arrays;
vector<svector<Z3_symbol> > m_sym_arrays;
vector<unsigned_vector> m_unsigned_arrays;
imp(z3_replayer & o, std::istream & in):
m_owner(o),
m_stream(in),
m_curr(0),
m_line(1) {
next();
}
void display_arg(std::ostream & out, value const & v) const {
switch (v.m_kind) {
case INT64:
out << v.m_int;
break;
case UINT64:
out << v.m_uint;
break;
case DOUBLE:
out << v.m_double;
break;
case STRING:
out << v.m_str;
break;
case SYMBOL:
out << symbol::mk_symbol_from_c_ptr(v.m_str);
break;
case OBJECT:
out << v.m_obj;
break;
case UINT_ARRAY:
case OBJECT_ARRAY:
case SYMBOL_ARRAY:
out << "<array>";
break;
default:
out << "<unknown>";
break;
}
}
void display_args(std::ostream & out) const {
for (unsigned i = 0; i < m_args.size(); i++) {
if (i > 0) out << " ";
display_arg(out, m_args[i]);
}
}
char curr() const { return m_curr; }
void new_line() { m_line++; }
void next() { m_curr = m_stream.get(); }
void read_string_core(char delimiter) {
if (curr() != delimiter)
throw z3_replayer_exception("invalid string/symbol");
m_string.reset();
next();
while (true) {
char c = curr();
if (c == EOF) {
throw z3_replayer_exception("unexpected end of file");
}
else if (c == '\n') {
throw z3_replayer_exception("unexpected end of line");
}
else if (c == '\\') {
next();
unsigned val = 0;
unsigned sz = 0;
while (sz < 3) {
c = curr();
if ('0' <= c && c <= '9') {
val *= 10;
val += c - '0';
sz++;
}
else {
throw z3_replayer_exception("invalid scaped character");
}
if (val > 255)
throw z3_replayer_exception("invalid scaped character");
next();
}
TRACE("z3_replayer_escape", tout << "val: " << val << "\n";);
m_string.push_back(static_cast<char>(val));
}
else if (c == delimiter) {
next();
m_string.push_back(0);
return;
}
else {
m_string.push_back(c);
next();
}
}
}
void read_string() {
read_string_core('"');
}
void read_quoted_symbol() {
read_string_core('|');
m_id = m_string.begin();
}
void read_int64() {
if (!(curr() == '-' || ('0' <= curr() && curr() <= '9')))
throw z3_replayer_exception("invalid integer");
bool sign = false;
if (curr() == '-') {
sign = true;
next();
if (!('0' <= curr() && curr() <= '9'))
throw z3_replayer_exception("invalid integer");
}
m_int64 = 0;
while (true) {
char c = curr();
if ('0' <= c && c <= '9') {
m_int64 = 10*m_int64 + (c - '0');
next();
}
else {
break;
}
}
if (sign)
m_int64 = -m_int64;
}
void read_uint64() {
if (!('0' <= curr() && curr() <= '9'))
throw z3_replayer_exception("invalid unsigned");
m_uint64 = 0;
while (true) {
char c = curr();
if ('0' <= c && c <= '9') {
m_uint64 = 10*m_uint64 + (c - '0');
next();
}
else {
break;
}
}
}
bool is_double_char() const {
return curr() == '-' || curr() == '.' || ('0' <= curr() && curr() <= '9') || curr() == 'e' || curr() == 'E';
}
void read_double() {
m_string.reset();
while (is_double_char()) {
m_string.push_back(curr());
next();
}
if (m_string.empty())
throw z3_replayer_exception("invalid double");
m_string.push_back(0);
char * ptr;
m_double = strtod(m_string.begin(), &ptr);
}
void read_ptr() {
if (!(('0' <= curr() && curr() <= '9') || ('A' <= curr() && curr() <= 'F') || ('a' <= curr() && curr() <= 'f')))
throw z3_replayer_exception("invalid ptr");
m_ptr = 0;
while (true) {
char c = curr();
if ('0' <= c && c <= '9') {
m_ptr = m_ptr * 16 + (c - '0');
}
else if ('a' <= c && c <= 'f') {
m_ptr = m_ptr * 16 + 10 + (c - 'a');
}
else if ('A' <= c && c <= 'F') {
m_ptr = m_ptr * 16 + 10 + (c - 'A');
}
else {
return;
}
next();
}
}
void skip_blank() {
while (true) {
char c = curr();
if (c == '\n') {
new_line();
next();
}
else if (c == ' ' || c == '\t') {
next();
}
else {
break;
}
}
}
void push_array(unsigned sz, value_kind k) {
unsigned asz = m_args.size();
if (sz > asz)
throw z3_replayer_exception("invalid array size");
__uint64 aidx;
value_kind nk;
for (unsigned i = asz - sz; i < asz; i++) {
if (m_args[i].m_kind != k)
throw z3_replayer_exception("invalid array: mixed value types");
}
if (k == UINT64) {
aidx = m_unsigned_arrays.size();
nk = UINT_ARRAY;
m_unsigned_arrays.push_back(unsigned_vector());
unsigned_vector & v = m_unsigned_arrays.back();
for (unsigned i = asz - sz; i < asz; i++) {
v.push_back(static_cast<unsigned>(m_args[i].m_uint));
}
}
else if (k == SYMBOL) {
aidx = m_sym_arrays.size();
nk = SYMBOL_ARRAY;
m_sym_arrays.push_back(svector<Z3_symbol>());
svector<Z3_symbol> & v = m_sym_arrays.back();
for (unsigned i = asz - sz; i < asz; i++) {
v.push_back(reinterpret_cast<Z3_symbol>(const_cast<char*>(m_args[i].m_str)));
}
}
else if (k == OBJECT) {
TRACE("z3_replayer_bug",
tout << "args: "; display_args(tout); tout << "\n";
tout << "push_back, sz: " << sz << ", m_obj_arrays.size(): " << m_obj_arrays.size() << "\n";
for (unsigned i = asz - sz; i < asz; i++) {
tout << "pushing: " << m_args[i].m_obj << "\n";
});
aidx = m_obj_arrays.size();
nk = OBJECT_ARRAY;
m_obj_arrays.push_back(ptr_vector<void>());
ptr_vector<void> & v = m_obj_arrays.back();
for (unsigned i = asz - sz; i < asz; i++) {
v.push_back(m_args[i].m_obj);
}
}
else {
throw z3_replayer_exception("unsupported array type");
}
m_args.shrink(asz - sz);
m_args.push_back(value(nk, aidx));
}
#define TICK_FREQUENCY 100000
void parse() {
unsigned long long counter = 0;
unsigned tick = 0;
while (true) {
IF_VERBOSE(1, {
counter++; tick++;
if (tick >= TICK_FREQUENCY) {
std::cout << "[replayer] " << counter << " operations executed" << std::endl;
tick = 0;
}
});
skip_blank();
char c = curr();
if (c == EOF)
return;
switch (c) {
case 'R':
// reset
next();
TRACE("z3_replayer", tout << "[" << m_line << "] " << "R\n";);
reset();
break;
case 'P': {
// push pointer
next(); skip_blank(); read_ptr();
TRACE("z3_replayer", tout << "[" << m_line << "] " << "P " << m_ptr << "\n";);
if (m_ptr == 0) {
m_args.push_back(0);
}
else {
void * obj = 0;
if (!m_heap.find(m_ptr, obj))
throw z3_replayer_exception("invalid pointer");
m_args.push_back(value(obj));
TRACE("z3_replayer_bug", tout << "args after 'P':\n"; display_args(tout); tout << "\n";);
}
break;
}
case 'S': {
// push string
next(); skip_blank(); read_string();
TRACE("z3_replayer", tout << "[" << m_line << "] " << "S " << m_string.begin() << "\n";);
symbol sym(m_string.begin()); // save string
m_args.push_back(value(STRING, sym.bare_str()));
break;
}
case 'N':
// push null symbol
next();
TRACE("z3_replayer", tout << "[" << m_line << "] " << "N\n";);
m_args.push_back(value(SYMBOL, static_cast<char const *>(0)));
break;
case '$': {
// push symbol
next(); skip_blank(); read_quoted_symbol();
TRACE("z3_replayer", tout << "[" << m_line << "] " << "$ " << m_id << "\n";);
m_args.push_back(value(SYMBOL, m_id.bare_str()));
break;
}
case '#': {
// push numeral symbol
next(); skip_blank(); read_uint64();
TRACE("z3_replayer", tout << "[" << m_line << "] " << "# " << m_uint64 << "\n";);
symbol sym(static_cast<unsigned>(m_uint64));
m_args.push_back(value(SYMBOL, static_cast<char const *>(sym.c_ptr())));
break;
}
case 'I':
// push integer;
next(); skip_blank(); read_int64();
TRACE("z3_replayer", tout << "[" << m_line << "] " << "I " << m_int64 << "\n";);
m_args.push_back(value(INT64, m_int64));
break;
case 'U':
// push unsigned;
next(); skip_blank(); read_uint64();
TRACE("z3_replayer", tout << "[" << m_line << "] " << "U " << m_uint64 << "\n";);
m_args.push_back(value(UINT64, m_uint64));
break;
case 'D':
// push double
next(); skip_blank(); read_double();
TRACE("z3_replayer", tout << "[" << m_line << "] " << "D " << m_double << "\n";);
m_args.push_back(value(DOUBLE, m_double));
break;
case 'p':
case 's':
case 'u':
// push array
next(); skip_blank(); read_uint64();
TRACE("z3_replayer", tout << "[" << m_line << "] " << "A " << m_uint64 << "\n";);
if (c == 'p')
push_array(static_cast<unsigned>(m_uint64), OBJECT);
else if (c == 's')
push_array(static_cast<unsigned>(m_uint64), SYMBOL);
else
push_array(static_cast<unsigned>(m_uint64), UINT64);
break;
case 'C': {
// call procedure
next(); skip_blank(); read_uint64();
TRACE("z3_replayer", tout << "[" << m_line << "] " << "C " << m_uint64 << "\n";);
unsigned idx = static_cast<unsigned>(m_uint64);
if (idx >= m_cmds.size())
throw z3_replayer_exception("invalid command");
try {
m_cmds[idx](m_owner);
}
catch (z3_error & ex) {
throw ex;
}
catch (z3_exception & ex) {
std::cout << "[z3 exception]: " << ex.msg() << std::endl;
}
break;
}
case '=':
// save result
// = obj_id
next(); skip_blank(); read_ptr();
TRACE("z3_replayer", tout << "[" << m_line << "] " << "= " << m_ptr << "\n";);
m_heap.insert(m_ptr, m_result);
break;
case '*': {
// save out
// @ obj_id pos
next(); skip_blank(); read_ptr(); skip_blank(); read_uint64();
unsigned pos = static_cast<unsigned>(m_uint64);
TRACE("z3_replayer", tout << "[" << m_line << "] " << "* " << m_ptr << " " << pos << "\n";);
if (pos >= m_args.size() || m_args[pos].m_kind != OBJECT)
throw_invalid_reference();
m_heap.insert(m_ptr, m_args[pos].m_obj);
break;
}
case '@': {
// save array out
// @ obj_id array_pos idx
next(); skip_blank(); read_ptr(); skip_blank(); read_uint64();
unsigned pos = static_cast<unsigned>(m_uint64);
if (pos >= m_args.size() || m_args[pos].m_kind != OBJECT_ARRAY)
throw_invalid_reference();
unsigned aidx = static_cast<unsigned>(m_args[pos].m_uint);
ptr_vector<void> & v = m_obj_arrays[aidx];
skip_blank(); read_uint64();
unsigned idx = static_cast<unsigned>(m_uint64);
TRACE("z3_replayer", tout << "[" << m_line << "] " << "@ " << m_ptr << " " << pos << " " << idx << "\n";);
TRACE("z3_replayer_bug", tout << "v[idx]: " << v[idx] << "\n";);
m_heap.insert(m_ptr, v[idx]);
break;
}
case 'M':
// user message
next(); skip_blank(); read_string();
TRACE("z3_replayer", tout << "[" << m_line << "] " << "M " << m_string.begin() << "\n";);
std::cout << m_string.begin() << "\n"; std::cout.flush();
break;
default:
TRACE("z3_replayer", tout << "unknown command " << c << "\n";);
throw z3_replayer_exception("unknown log command");
break;
}
}
}
int get_int(unsigned pos) const {
if (pos >= m_args.size() || m_args[pos].m_kind != INT64)
throw_invalid_reference();
return static_cast<int>(m_args[pos].m_int);
}
__int64 get_int64(unsigned pos) const {
if (pos >= m_args.size() || m_args[pos].m_kind != INT64)
throw_invalid_reference();
return m_args[pos].m_int;
}
unsigned get_uint(unsigned pos) const {
if (pos >= m_args.size() || m_args[pos].m_kind != UINT64)
throw_invalid_reference();
return static_cast<unsigned>(m_args[pos].m_uint);
}
__uint64 get_uint64(unsigned pos) const {
if (pos >= m_args.size() || m_args[pos].m_kind != UINT64)
throw_invalid_reference();
return m_args[pos].m_uint;
}
double get_double(unsigned pos) const {
if (pos >= m_args.size() || m_args[pos].m_kind != DOUBLE)
throw_invalid_reference();
return m_args[pos].m_double;
}
Z3_string get_str(unsigned pos) const {
if (pos >= m_args.size() || m_args[pos].m_kind != STRING)
throw_invalid_reference();
return m_args[pos].m_str;
}
Z3_symbol get_symbol(unsigned pos) const {
if (pos >= m_args.size() || m_args[pos].m_kind != SYMBOL)
throw_invalid_reference();
return reinterpret_cast<Z3_symbol>(const_cast<char*>(m_args[pos].m_str));
}
void * get_obj(unsigned pos) const {
if (pos >= m_args.size() || m_args[pos].m_kind != OBJECT)
throw_invalid_reference();
return m_args[pos].m_obj;
}
unsigned * get_uint_array(unsigned pos) const {
if (pos >= m_args.size() || m_args[pos].m_kind != UINT_ARRAY)
throw_invalid_reference();
unsigned idx = static_cast<unsigned>(m_args[pos].m_uint);
return m_unsigned_arrays[idx].c_ptr();
}
Z3_symbol * get_symbol_array(unsigned pos) const {
if (pos >= m_args.size() || m_args[pos].m_kind != SYMBOL_ARRAY)
throw_invalid_reference();
unsigned idx = static_cast<unsigned>(m_args[pos].m_uint);
return m_sym_arrays[idx].c_ptr();
}
void ** get_obj_array(unsigned pos) const {
if (pos >= m_args.size() || m_args[pos].m_kind != OBJECT_ARRAY)
throw_invalid_reference();
unsigned idx = static_cast<unsigned>(m_args[pos].m_uint);
ptr_vector<void> const & v = m_obj_arrays[idx];
TRACE("z3_replayer_bug", tout << "pos: " << pos << ", idx: " << idx << " size(): " << v.size() << "\n";
for (unsigned i = 0; i < v.size(); i++) tout << v[i] << " "; tout << "\n";);
return v.c_ptr();
}
int * get_int_addr(unsigned pos) {
if (pos >= m_args.size() || m_args[pos].m_kind != INT64)
throw_invalid_reference();
return reinterpret_cast<int*>(&(m_args[pos].m_int));
}
__int64 * get_int64_addr(unsigned pos) {
if (pos >= m_args.size() || m_args[pos].m_kind != INT64)
throw_invalid_reference();
return &(m_args[pos].m_int);
}
unsigned * get_uint_addr(unsigned pos) {
if (pos >= m_args.size() || m_args[pos].m_kind != UINT64)
throw_invalid_reference();
return reinterpret_cast<unsigned*>(&(m_args[pos].m_uint));
}
__uint64 * get_uint64_addr(unsigned pos) {
if (pos >= m_args.size() || m_args[pos].m_kind != UINT64)
throw_invalid_reference();
return &(m_args[pos].m_uint);
}
Z3_string * get_str_addr(unsigned pos) {
if (pos >= m_args.size() || m_args[pos].m_kind != STRING)
throw_invalid_reference();
return &(m_args[pos].m_str);
}
void ** get_obj_addr(unsigned pos) {
if (pos >= m_args.size() || m_args[pos].m_kind != OBJECT)
throw_invalid_reference();
return &(m_args[pos].m_obj);
}
void store_result(void * obj) {
m_result = obj;
}
void register_cmd(unsigned id, z3_replayer_cmd cmd) {
m_cmds.reserve(id+1, 0);
m_cmds[id] = cmd;
}
void reset() {
m_result = 0;
m_args.reset();
m_obj_arrays.reset();
m_sym_arrays.reset();
m_unsigned_arrays.reset();
}
};
z3_replayer::z3_replayer(std::istream & in) {
m_imp = alloc(imp, *this, in);
register_z3_replayer_cmds(*this);
}
z3_replayer::~z3_replayer() {
dealloc(m_imp);
}
unsigned z3_replayer::get_line() const {
return m_imp->m_line;
}
bool z3_replayer::get_bool(unsigned pos) const {
return get_int(pos) != 0;
}
int z3_replayer::get_int(unsigned pos) const {
return m_imp->get_int(pos);
}
unsigned z3_replayer::get_uint(unsigned pos) const {
return m_imp->get_uint(pos);
}
__int64 z3_replayer::get_int64(unsigned pos) const {
return m_imp->get_int64(pos);
}
__uint64 z3_replayer::get_uint64(unsigned pos) const {
return m_imp->get_uint64(pos);
}
double z3_replayer::get_double(unsigned pos) const {
return m_imp->get_double(pos);
}
Z3_string z3_replayer::get_str(unsigned pos) const {
return m_imp->get_str(pos);
}
Z3_symbol z3_replayer::get_symbol(unsigned pos) const {
return m_imp->get_symbol(pos);
}
void * z3_replayer::get_obj(unsigned pos) const {
return m_imp->get_obj(pos);
}
unsigned * z3_replayer::get_uint_array(unsigned pos) const {
return m_imp->get_uint_array(pos);
}
Z3_symbol * z3_replayer::get_symbol_array(unsigned pos) const {
return m_imp->get_symbol_array(pos);
}
void ** z3_replayer::get_obj_array(unsigned pos) const {
return m_imp->get_obj_array(pos);
}
int * z3_replayer::get_int_addr(unsigned pos) {
return m_imp->get_int_addr(pos);
}
__int64 * z3_replayer::get_int64_addr(unsigned pos) {
return m_imp->get_int64_addr(pos);
}
unsigned * z3_replayer::get_uint_addr(unsigned pos) {
return m_imp->get_uint_addr(pos);
}
__uint64 * z3_replayer::get_uint64_addr(unsigned pos) {
return m_imp->get_uint64_addr(pos);
}
Z3_string * z3_replayer::get_str_addr(unsigned pos) {
return m_imp->get_str_addr(pos);
}
void ** z3_replayer::get_obj_addr(unsigned pos) {
return m_imp->get_obj_addr(pos);
}
void z3_replayer::store_result(void * obj) {
return m_imp->store_result(obj);
}
void z3_replayer::register_cmd(unsigned id, z3_replayer_cmd cmd) {
return m_imp->register_cmd(id, cmd);
}
void z3_replayer::parse() {
return m_imp->parse();
}

66
src/api/z3_replayer.h Normal file
View file

@ -0,0 +1,66 @@
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
z3_replayer.h
Abstract:
Interpreter for Z3 logs
Author:
Leonardo de Moura (leonardo) 2011-09-22
Notes:
--*/
#ifndef _Z3_REPLAYER_H_
#define _Z3_REPLAYER_H_
#include<iostream>
#include"z3.h"
#include"z3_exception.h"
class z3_replayer;
typedef void (*z3_replayer_cmd)(z3_replayer &);
typedef default_exception z3_replayer_exception;
class z3_replayer {
struct imp;
imp * m_imp;
public:
z3_replayer(std::istream & in);
~z3_replayer();
void parse();
unsigned get_line() const;
int get_int(unsigned pos) const;
unsigned get_uint(unsigned pos) const;
__int64 get_int64(unsigned pos) const;
__uint64 get_uint64(unsigned pos) const;
double get_double(unsigned pos) const;
bool get_bool(unsigned pos) const;
Z3_string get_str(unsigned pos) const;
Z3_symbol get_symbol(unsigned pos) const;
void * get_obj(unsigned pos) const;
unsigned * get_uint_array(unsigned pos) const;
Z3_symbol * get_symbol_array(unsigned pos) const;
void ** get_obj_array(unsigned pos) const;
int * get_int_addr(unsigned pos);
__int64 * get_int64_addr(unsigned pos);
unsigned * get_uint_addr(unsigned pos);
__uint64 * get_uint64_addr(unsigned pos);
Z3_string * get_str_addr(unsigned pos);
void ** get_obj_addr(unsigned pos);
void store_result(void * obj);
void register_cmd(unsigned id, z3_replayer_cmd cmd);
};
#endif

1304
src/api/z3_solver.cpp Normal file

File diff suppressed because it is too large Load diff

1007
src/api/z3_solver.h Normal file

File diff suppressed because it is too large Load diff

64
src/api/z3_v1.h Normal file
View file

@ -0,0 +1,64 @@
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
z3_v1.h
Abstract:
Z3 1.x backwards compatibility macros.
These macros are used to simulate the Z3 API using in the 1.x versions.
This file should only be used by users still using the Z3 1.x API.
Author:
Leonardo de Moura (leonardo) 2011-09-22
Notes:
--*/
#ifndef _Z3_V1_H_
#define _Z3_V1_H_
#include"z3.h"
// Backwards compatibility
#define Z3_type_ast Z3_sort
#define Z3_const_decl_ast Z3_func_decl
#define Z3_const Z3_app
#define Z3_pattern_ast Z3_pattern
#define Z3_UNINTERPRETED_TYPE Z3_UNINTERPRETED_SORT
#define Z3_BOOL_TYPE Z3_BOOL_SORT
#define Z3_INT_TYPE Z3_INT_SORT
#define Z3_REAL_TYPE Z3_REAL_SORT
#define Z3_BV_TYPE Z3_BV_SORT
#define Z3_ARRAY_TYPE Z3_ARRAY_SORT
#define Z3_TUPLE_TYPE Z3_DATATYPE_SORT
#define Z3_UNKNOWN_TYPE Z3_UNKNOWN_SORT
#define Z3_CONST_DECL_AST Z3_FUNC_DECL_AST
#define Z3_TYPE_AST Z3_SORT_AST
#define Z3_SORT_ERROR Z3_TYPE_ERROR
#define Z3_mk_uninterpreted_type Z3_mk_uninterpreted_sort
#define Z3_mk_bool_type Z3_mk_bool_sort
#define Z3_mk_int_type Z3_mk_int_sort
#define Z3_mk_real_type Z3_mk_real_sort
#define Z3_mk_bv_type Z3_mk_bv_sort
#define Z3_mk_array_type Z3_mk_array_sort
#define Z3_mk_tuple_type Z3_mk_tuple_sort
#define Z3_get_type Z3_get_sort
#define Z3_get_pattern_ast Z3_get_pattern
#define Z3_get_type_kind Z3_get_sort_kind
#define Z3_get_type_name Z3_get_sort_name
#define Z3_get_bv_type_size Z3_get_bv_sort_size
#define Z3_get_array_type_domain Z3_get_array_sort_domain
#define Z3_get_array_type_range Z3_get_array_sort_range
#define Z3_get_tuple_type_num_fields Z3_get_tuple_sort_num_fields
#define Z3_get_tuple_type_field_decl Z3_get_tuple_sort_field_decl
#define Z3_get_tuple_type_mk_decl Z3_get_tuple_sort_mk_decl
#define Z3_to_const_ast Z3_to_app
#define Z3_get_numeral_value_string Z3_get_numeral_string
#define Z3_get_const_ast_decl Z3_get_app_decl
#define Z3_get_value Z3_eval_func_decl
#endif

1
src/assertion_set/README Normal file
View file

@ -0,0 +1 @@
This module is obsolete. It is subsumed by the tactic module.

View 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;
}

View 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

View 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();
}

View 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

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,223 @@
/*++
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);
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;)
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

View 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);
}

View 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

View file

@ -0,0 +1,94 @@
/*++
Copyright (c) 2012 Microsoft Corporation
Module Name:
der_strategy.cpp
Abstract:
DER strategy
Author:
Leonardo de Moura (leonardo) 2012-10-20
--*/
#include"der_strategy.h"
struct der_strategy::imp {
ast_manager & m_manager;
der_rewriter m_r;
imp(ast_manager & m):
m_manager(m),
m_r(m) {
}
ast_manager & m() const { return m_manager; }
void set_cancel(bool f) {
m_r.set_cancel(f);
}
void reset() {
m_r.reset();
}
void operator()(assertion_set & s) {
SASSERT(is_well_sorted(s));
as_st_report report("der", s);
TRACE("before_der", s.display(tout););
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);
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);
}
s.elim_redundancies();
TRACE("after_der", s.display(tout););
SASSERT(is_well_sorted(s));
}
};
der_strategy::der_strategy(ast_manager & m) {
m_imp = alloc(imp, m);
}
der_strategy::~der_strategy() {
dealloc(m_imp);
}
void der_strategy::operator()(assertion_set & s) {
m_imp->operator()(s);
}
void der_strategy::set_cancel(bool f) {
if (m_imp)
m_imp->set_cancel(f);
}
void der_strategy::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);
#pragma omp critical (as_st_cancel)
{
m_imp = d;
}
}

View file

@ -0,0 +1,47 @@
/*++
Copyright (c) 2012 Microsoft Corporation
Module Name:
der_strategy.h
Abstract:
DER strategy
Author:
Leonardo de Moura (leonardo) 2012-10-20
--*/
#ifndef _DER_STRATEGY_H_
#define _DER_STRATEGY_H_
#include"der.h"
#include"assertion_set_strategy.h"
// TODO: delete obsolete class
class der_strategy : public assertion_set_strategy {
struct imp;
imp * m_imp;
public:
der_strategy(ast_manager & m);
virtual ~der_strategy();
void operator()(assertion_set & s);
virtual void operator()(assertion_set & s, model_converter_ref & mc) {
operator()(s);
mc = 0;
}
virtual void cleanup();
virtual void set_cancel(bool f);
};
inline as_st * mk_der(ast_manager & m) {
return alloc(der_strategy, m);
}
#endif

View file

@ -0,0 +1,232 @@
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
elim_distinct.cpp
Abstract:
Replace one distinct(t0, ..., tn) with (t0 = 0 and ... and tn = n)
when the sort of t0...tn is uninterpreted.
Author:
Leonardo de Moura (leonardo) 2011-04-28
Revision History:
--*/
#include"elim_distinct.h"
#include"assertion_set.h"
#include"model_converter.h"
#include"arith_decl_plugin.h"
#include"rewriter_def.h"
#include"critical_flet.h"
struct elim_distinct::imp {
struct mc : public model_converter {
ast_ref_vector m_asts;
sort * m_usort;
obj_map<func_decl, func_decl *> m_inv_map;
public:
mc(ast_manager & m):m_asts(m) {
}
};
struct u2i_cfg : public default_rewriter_cfg {
arith_util m_autil;
ast_ref_vector m_asts;
sort * m_usort;
sort * m_int_sort;
obj_map<func_decl, func_decl *> m_f2f;
ast_manager & m() const { return m_asts.get_manager(); }
bool must_remap(func_decl * f) const {
if (f->get_range() == m_usort)
return true;
for (unsigned i = 0; i < f->get_arity(); i++) {
if (f->get_domain(i) == m_usort)
return true;
}
return false;
}
sort * remap(sort * s) {
return (s == m_usort) ? m_int_sort : s;
}
func_decl * remap(func_decl * f) {
ptr_buffer<sort> new_domain;
sort * new_range = remap(f->get_range());
for (unsigned i = 0; i < f->get_arity(); i++)
new_domain.push_back(remap(f->get_domain(i)));
func_decl * new_f = m().mk_func_decl(f->get_name(), new_domain.size(), new_domain.c_ptr(), new_range);
m_asts.push_back(new_f);
m_asts.push_back(f);
m_f2f.insert(f, new_f);
return new_f;
}
br_status reduce_app(func_decl * f, unsigned num, expr * const * args, expr_ref & result, proof_ref & result_pr) {
result_pr = 0;
func_decl * new_f;
if (m_f2f.find(f, new_f)) {
result = m().mk_app(new_f, num, args);
return BR_DONE;
}
if (!must_remap(f))
return BR_FAILED;
if (m().is_eq(f)) {
result = m().mk_eq(args[0], args[1]);
return BR_DONE;
}
if (m().is_ite(f)) {
result = m().mk_ite(args[0], args[1], args[2]);
return BR_DONE;
}
if (f->get_family_id() != null_family_id || f->get_info() != 0) {
throw elim_distinct_exception("uninterpreted sort is used in interpreted function symbol");
}
new_f = remap(f);
result = m().mk_app(new_f, num, args);
return BR_DONE;
}
bool reduce_quantifier(quantifier * old_q,
expr * new_body,
expr * const * new_patterns,
expr * const * new_no_patterns,
expr_ref & result,
proof_ref & result_pr) {
throw elim_distinct_exception("elim-distinct tactic does not support quantifiers");
}
u2i_cfg(ast_manager & m, sort * u):
m_autil(m),
m_asts(m),
m_usort(u) {
m_asts.push_back(u);
m_int_sort = m_autil.mk_int();
m_asts.push_back(m_int_sort);
}
};
class u2i : public rewriter_tpl<u2i_cfg> {
u2i_cfg m_cfg;
public:
u2i(ast_manager & m, sort * u):
rewriter_tpl<u2i_cfg>(m, false, m_cfg),
m_cfg(m, u) {
if (m.proofs_enabled())
throw elim_distinct_exception("elim-distinct tactic does not support proof generation");
}
arith_util & autil() { return cfg().m_autil; }
};
ast_manager & m_manager;
u2i * m_u2i;
imp(ast_manager & m):m_manager(m), m_u2i(0) {}
ast_manager & m() const { return m_manager; }
bool is_distinct(expr * t) {
if (!m().is_distinct(t))
return false;
if (to_app(t)->get_num_args() == 0)
return false;
return m().is_uninterp(m().get_sort(to_app(t)->get_arg(0)));
}
model_converter * operator()(assertion_set & s, app * d) {
if (d && !is_distinct(d))
d = 0;
app * r = 0;
unsigned sz = s.size();
for (unsigned i = 0; i < sz; i++) {
expr * curr = s.form(i);
if (curr == d)
break;
if (is_distinct(curr)) {
if (!r || to_app(curr)->get_num_args() > r->get_num_args())
r = to_app(curr);
}
}
if (d != 0)
r = d;
if (r == 0)
return 0;
sort * u = m().get_sort(to_app(r)->get_arg(0));
u2i conv(m(), u);
{
critical_flet<u2i*> l1(m_u2i, &conv);
expr_ref new_curr(m());
for (unsigned i = 0; i < sz; i++) {
expr * curr = s.form(i);
if (curr == r) {
unsigned num = r->get_num_args();
for (unsigned j = 0; j < num; j++) {
expr * arg = r->get_arg(j);
conv(arg, new_curr);
expr * eq = m().mk_eq(new_curr, conv.autil().mk_numeral(rational(j), true));
s.assert_expr(eq);
}
new_curr = m().mk_true();
}
else {
conv(curr, new_curr);
}
s.update(i, new_curr);
}
}
// TODO: create model converter
return 0;
}
void cancel() {
// Remark: m_u2i is protected by the omp global critical section.
// If this is a performance problem, then replace critical_flet by a custom flet that uses a different
// section name
#pragma omp critical (critical_flet)
{
if (m_u2i)
m_u2i->cancel();
}
}
};
template class rewriter_tpl<elim_distinct::imp::u2i_cfg>;
elim_distinct::elim_distinct(ast_manager & m) {
m_imp = alloc(imp, m);
}
elim_distinct::~elim_distinct() {
dealloc(m_imp);
}
model_converter * elim_distinct::operator()(assertion_set & s, app * d) {
return m_imp->operator()(s, d);
}
void elim_distinct::cancel() {
m_imp->cancel();
}
void elim_distinct::reset() {
cleanup();
}
void elim_distinct::cleanup() {
ast_manager & m = m_imp->m();
dealloc(m_imp);
m_imp = alloc(imp, m);
}

View file

@ -0,0 +1,54 @@
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
elim_distinct.h
Abstract:
Replace one distinct(t0, ..., tn) with (t0 = 0 and ... and tn = n)
when the sort of t0...tn is uninterpreted.
Author:
Leonardo de Moura (leonardo) 2011-04-28
Revision History:
--*/
#ifndef _ELIM_DISTINCT_H_
#define _ELIM_DISTINCT_H_
#include"assertion_set.h"
class model_converter;
class ast_manager;
class assertion_set;
class elim_distinct_exception : public default_exception {
public:
elim_distinct_exception(char const * msg):default_exception(msg) {}
};
class elim_distinct {
struct imp;
imp * m_imp;
public:
elim_distinct(ast_manager & m);
~elim_distinct();
/**
\brief It throws an elim_distinct_exception if the strategy failed.
If d == 0, then search for the biggest distinct(t0, ..., tn) in the assertion set.
if d != 0, then succeed only if d is in the assertion set.
*/
model_converter * operator()(assertion_set & s, app * d);
void cancel();
void reset();
void cleanup();
};
#endif

View file

@ -0,0 +1,120 @@
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
elim_var_model_converter.cpp
Abstract:
Model converter that introduces eliminated variables in a model.
Author:
Leonardo (leonardo) 2011-05-05
Notes:
--*/
#include"elim_var_model_converter.h"
#include"model_evaluator.h"
#include"ast_smt2_pp.h"
#include"model_v2_pp.h"
#include"ast_pp.h"
elim_var_model_converter::~elim_var_model_converter() {
}
struct elim_var_model_converter::set_eval {
elim_var_model_converter * m_owner;
model_evaluator * m_old;
set_eval(elim_var_model_converter * owner, model_evaluator * ev) {
m_owner = owner;
m_old = owner->m_eval;
#pragma omp critical (elim_var_model_converter)
{
owner->m_eval = ev;
}
}
~set_eval() {
#pragma omp critical (elim_var_model_converter)
{
m_owner->m_eval = m_old;
}
}
};
static void display_decls_info(std::ostream & out, model_ref & md) {
ast_manager & m = md->get_manager();
unsigned sz = md->get_num_decls();
for (unsigned i = 0; i < sz; i++) {
func_decl * d = md->get_decl(i);
out << d->get_name();
out << " (";
for (unsigned j = 0; j < d->get_arity(); j++)
out << mk_pp(d->get_domain(j), m);
out << mk_pp(d->get_range(), m);
out << ") ";
if (d->get_info())
out << *(d->get_info());
out << " :id " << d->get_id() << "\n";
}
}
void elim_var_model_converter::operator()(model_ref & md) {
TRACE("elim_var_mc", model_v2_pp(tout, *md); display_decls_info(tout, md););
model_evaluator ev(*(md.get()));
ev.set_model_completion(true);
expr_ref val(m());
{
set_eval setter(this, &ev);
unsigned i = m_vars.size();
while (i > 0) {
--i;
expr * def = m_defs.get(i);
ev(def, val);
TRACE("elim_var_mc", tout << m_vars.get(i)->get_name() << " ->\n" << mk_ismt2_pp(def, m()) << "\n==>\n" << mk_ismt2_pp(val, m()) << "\n";);
func_decl * f = m_vars.get(i);
unsigned arity = f->get_arity();
if (arity == 0) {
md->register_decl(f, val);
}
else {
func_interp * new_fi = alloc(func_interp, m(), arity);
new_fi->set_else(val);
md->register_decl(f, new_fi);
}
}
}
TRACE("elim_var_mc", model_v2_pp(tout, *md); display_decls_info(tout, md););
}
void elim_var_model_converter::cancel() {
#pragma omp critical (elim_var_model_converter)
{
if (m_eval)
m_eval->cancel();
}
}
void elim_var_model_converter::display(std::ostream & out) {
ast_manager & m = m_vars.get_manager();
out << "(elim-var-model-converter";
for (unsigned i = 0; i < m_vars.size(); i++) {
out << "\n (" << m_vars.get(i)->get_name() << " ";
unsigned indent = m_vars.get(i)->get_name().size() + 4;
out << mk_ismt2_pp(m_defs.get(i), m, indent) << ")";
}
out << ")" << std::endl;
}
model_converter * elim_var_model_converter::translate(ast_translation & translator) {
elim_var_model_converter * res = alloc(elim_var_model_converter, translator.to());
for (unsigned i = 0; i < m_vars.size(); i++)
res->m_vars.push_back(translator(m_vars[i].get()));
for (unsigned i = 0; i < m_defs.size(); i++)
res->m_defs.push_back(translator(m_defs[i].get()));
// m_eval is a transient object. So, it doesn't need to be translated.
return res;
}

View file

@ -0,0 +1,56 @@
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
elim_var_model_converter.h
Abstract:
Model converter that introduces eliminated variables in a model.
Author:
Leonardo (leonardo) 2011-05-05
Notes:
--*/
#ifndef _ELIM_VAR_MODEL_CONVERTER_H_
#define _ELIM_VAR_MODEL_CONVERTER_H_
#include"ast.h"
#include"model_converter.h"
class model_evaluator;
class elim_var_model_converter : public model_converter {
func_decl_ref_vector m_vars;
expr_ref_vector m_defs;
model_evaluator * m_eval;
struct set_eval;
public:
elim_var_model_converter(ast_manager & m):m_vars(m), m_defs(m), m_eval(0) {
}
virtual ~elim_var_model_converter();
ast_manager & m() const { return m_vars.get_manager(); }
virtual void operator()(model_ref & md);
virtual void cancel();
virtual void display(std::ostream & out);
// register a variable that was eliminated
void insert(func_decl * v, expr * def) {
m_vars.push_back(v);
m_defs.push_back(def);
}
virtual model_converter * translate(ast_translation & translator);
};
#endif

View file

@ -0,0 +1,775 @@
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
gaussian_elim.cpp
Abstract:
(extended) Gaussian elimination for assertion sets.
It also supports other theories besides arithmetic.
Author:
Leonardo (leonardo) 2011-04-29
Notes:
--*/
#include"gaussian_elim.h"
#include"ast.h"
#include"expr_replacer.h"
#include"model_converter.h"
#include"assertion_set.h"
#include"ast_smt2_pp.h"
#include"elim_var_model_converter.h"
#include"occurs.h"
#include"cooperate.h"
#include"assertion_set_util.h"
struct gaussian_elim::imp {
ast_manager & m_manager;
expr_replacer * m_r;
bool m_r_owner;
arith_util m_a_util;
obj_map<expr, unsigned> m_num_occs;
unsigned m_num_steps;
unsigned m_num_eliminated_vars;
bool m_produce_models;
bool m_theory_solver;
bool m_ite_solver;
unsigned m_max_occs;
void updt_params(params_ref const & p) {
m_produce_models = p.get_bool(":produce-models", false);
m_ite_solver = p.get_bool(":ite-solver", true);
m_theory_solver = p.get_bool(":theory-solver", true);
m_max_occs = p.get_uint(":gaussian-max-occs", UINT_MAX);
}
typedef elim_var_model_converter gmc;
expr_substitution m_subst;
expr_substitution m_norm_subst;
expr_sparse_mark m_candidate_vars;
expr_sparse_mark m_candidate_set;
ptr_vector<expr> m_candidates;
ptr_vector<app> m_vars;
ptr_vector<app> m_ordered_vars;
volatile bool m_cancel;
imp(ast_manager & m, params_ref const & p, expr_replacer * r, bool owner):
m_manager(m),
m_r(r),
m_r_owner(r == 0 || owner),
m_a_util(m),
m_num_steps(0),
m_num_eliminated_vars(0),
m_subst(m),
m_norm_subst(m),
m_cancel(false) {
updt_params(p);
if (m_r == 0)
m_r = mk_default_expr_replacer(m);
}
~imp() {
if (m_r_owner)
dealloc(m_r);
}
ast_manager & m() const { return m_manager; }
bool check_occs(expr * t) const {
if (m_max_occs == UINT_MAX)
return true;
unsigned num = 0;
m_num_occs.find(t, num);
TRACE("gaussian_check_occs", tout << mk_ismt2_pp(t, m_manager) << " num_occs: " << num << " max: " << m_max_occs << "\n";);
return num <= m_max_occs;
}
// Use: (= x def) and (= def x)
bool trivial_solve(expr * lhs, expr * rhs, app_ref & var, expr_ref & def, proof_ref & pr) {
if (is_uninterp_const(lhs) && !m_candidate_vars.is_marked(lhs) && !occurs(lhs, rhs) && check_occs(lhs)) {
var = to_app(lhs);
def = rhs;
pr = 0;
return true;
}
else if (is_uninterp_const(rhs) && !m_candidate_vars.is_marked(rhs) && !occurs(rhs, lhs) && check_occs(rhs)) {
var = to_app(rhs);
def = lhs;
if (m_manager.proofs_enabled())
pr = m().mk_commutativity(m().mk_eq(lhs, rhs));
return true;
}
return false;
}
// (ite c (= x t1) (= x t2)) --> (= x (ite c t1 t2))
bool solve_ite_core(app * ite, expr * lhs1, expr * rhs1, expr * lhs2, expr * rhs2, app_ref & var, expr_ref & def, proof_ref & pr) {
if (lhs1 != lhs2)
return false;
if (!is_uninterp_const(lhs1) || m_candidate_vars.is_marked(lhs1))
return false;
if (occurs(lhs1, ite->get_arg(0)) || occurs(lhs1, rhs1) || occurs(lhs1, rhs2))
return false;
if (!check_occs(lhs1))
return false;
var = to_app(lhs1);
def = m().mk_ite(ite->get_arg(0), rhs1, rhs2);
if (m().proofs_enabled())
pr = m().mk_rewrite(ite, m().mk_eq(var, def));
return true;
}
// (ite c (= x t1) (= x t2)) --> (= x (ite c t1 t2))
bool solve_ite(app * ite, app_ref & var, expr_ref & def, proof_ref & pr) {
expr * t = ite->get_arg(1);
expr * e = ite->get_arg(2);
if (!m().is_eq(t) || !m().is_eq(e))
return false;
expr * lhs1 = to_app(t)->get_arg(0);
expr * rhs1 = to_app(t)->get_arg(1);
expr * lhs2 = to_app(e)->get_arg(0);
expr * rhs2 = to_app(e)->get_arg(1);
return
solve_ite_core(ite, lhs1, rhs1, lhs2, rhs2, var, def, pr) ||
solve_ite_core(ite, rhs1, lhs1, lhs2, rhs2, var, def, pr) ||
solve_ite_core(ite, lhs1, rhs1, rhs2, lhs2, var, def, pr) ||
solve_ite_core(ite, rhs1, lhs1, rhs2, lhs2, var, def, pr);
}
bool is_pos_literal(expr * n) {
return is_app(n) && to_app(n)->get_num_args() == 0 && to_app(n)->get_family_id() == null_family_id;
}
bool is_neg_literal(expr * n) {
if (m_manager.is_not(n))
return is_pos_literal(to_app(n)->get_arg(0));
return false;
}
#if 0
bool not_bool_eq(expr * f, app_ref & var, expr_ref & def, proof_ref & pr) {
if (!m().is_not(f))
return false;
expr * eq = to_app(f)->get_arg(0);
if (!m().is_eq(f))
return false;
}
#endif
/**
\brief Given t of the form (f s_0 ... s_n),
return true if x occurs in some s_j for j != i
*/
bool occurs_except(expr * x, app * t, unsigned i) {
unsigned num = t->get_num_args();
for (unsigned j = 0; j < num; j++) {
if (i != j && occurs(x, t->get_arg(j)))
return true;
}
return false;
}
bool solve_arith_core(app * lhs, expr * rhs, expr * eq, app_ref & var, expr_ref & def, proof_ref & pr) {
SASSERT(m_a_util.is_add(lhs));
bool is_int = m_a_util.is_int(lhs);
expr * a;
expr * v;
rational a_val;
unsigned num = lhs->get_num_args();
unsigned i;
for (i = 0; i < num; i++) {
expr * arg = lhs->get_arg(i);
if (is_uninterp_const(arg) && !m_candidate_vars.is_marked(arg) && check_occs(arg) && !occurs(arg, rhs) && !occurs_except(arg, lhs, i)) {
a_val = rational(1);
v = arg;
break;
}
else if (m_a_util.is_mul(arg, a, v) &&
is_uninterp_const(v) && !m_candidate_vars.is_marked(v) &&
m_a_util.is_numeral(a, a_val) &&
!a_val.is_zero() &&
(!is_int || a_val.is_minus_one()) &&
check_occs(v) &&
!occurs(v, rhs) &&
!occurs_except(v, lhs, i)) {
break;
}
}
if (i == num)
return false;
var = to_app(v);
expr_ref inv_a(m());
if (!a_val.is_one()) {
inv_a = m_a_util.mk_numeral(rational(1)/a_val, is_int);
rhs = m_a_util.mk_mul(inv_a, rhs);
}
ptr_buffer<expr> other_args;
for (unsigned j = 0; j < num; j++) {
if (i != j) {
if (inv_a)
other_args.push_back(m_a_util.mk_mul(inv_a, lhs->get_arg(j)));
else
other_args.push_back(lhs->get_arg(j));
}
}
switch (other_args.size()) {
case 0:
def = rhs;
break;
case 1:
def = m_a_util.mk_sub(rhs, other_args[0]);
break;
default:
def = m_a_util.mk_sub(rhs, m_a_util.mk_add(other_args.size(), other_args.c_ptr()));
break;
}
if (m().proofs_enabled()) {
pr = m().mk_rewrite(eq, m().mk_eq(var, def));
}
return true;
}
bool solve_arith(expr * lhs, expr * rhs, expr * eq, app_ref & var, expr_ref & def, proof_ref & pr) {
return
(m_a_util.is_add(lhs) && solve_arith_core(to_app(lhs), rhs, eq, var, def, pr)) ||
(m_a_util.is_add(rhs) && solve_arith_core(to_app(rhs), lhs, eq, var, def, pr));
}
bool solve(expr * f, app_ref & var, expr_ref & def, proof_ref & pr) {
if (m().is_eq(f)) {
if (trivial_solve(to_app(f)->get_arg(0), to_app(f)->get_arg(1), var, def, pr))
return true;
if (m_theory_solver) {
expr * lhs = to_app(f)->get_arg(0);
expr * rhs = to_app(f)->get_arg(1);
if (solve_arith(lhs, rhs, f, var, def, pr))
return true;
}
return false;
}
if (m().is_iff(f))
return trivial_solve(to_app(f)->get_arg(0), to_app(f)->get_arg(1), var, def, pr);
#if 0
if (not_bool_eq(f, var, def, pr))
return true;
#endif
if (m_ite_solver && m().is_ite(f))
return solve_ite(to_app(f), var, def, pr);
if (is_pos_literal(f)) {
if (m_candidate_vars.is_marked(f))
return false;
var = to_app(f);
def = m().mk_true();
if (m().proofs_enabled()) {
// [rewrite]: (iff (iff l true) l)
// [symmetry T1]: (iff l (iff l true))
pr = m().mk_rewrite(m().mk_eq(var, def), var);
pr = m().mk_symmetry(pr);
}
TRACE("gaussian_elim_bug2", tout << "eliminating: " << mk_ismt2_pp(f, m()) << "\n";);
return true;
}
if (is_neg_literal(f)) {
var = to_app(to_app(f)->get_arg(0));
if (m_candidate_vars.is_marked(var))
return false;
def = m().mk_false();
if (m().proofs_enabled()) {
// [rewrite]: (iff (iff l false) ~l)
// [symmetry T1]: (iff ~l (iff l false))
pr = m().mk_rewrite(m().mk_eq(var, def), f);
pr = m().mk_symmetry(pr);
}
return true;
}
return false;
}
void checkpoint() {
if (m_cancel)
throw gaussian_elim_exception(STE_CANCELED_MSG);
cooperate("gaussian elimination");
}
/**
\brief Start collecting candidates
*/
void collect(assertion_set & set) {
m_subst.reset();
m_norm_subst.reset();
m_r->set_substitution(0);
m_candidate_vars.reset();
m_candidate_set.reset();
m_candidates.reset();
m_vars.reset();
app_ref var(m());
expr_ref def(m());
proof_ref pr(m());
unsigned size = set.size();
for (unsigned idx = 0; idx < size; idx++) {
checkpoint();
expr * f = set.form(idx);
if (solve(f, var, def, pr)) {
m_vars.push_back(var);
m_candidates.push_back(f);
m_candidate_set.mark(f);
m_candidate_vars.mark(var);
if (m().proofs_enabled()) {
if (pr == 0)
pr = set.pr(idx);
else
pr = m().mk_modus_ponens(set.pr(idx), pr);
}
m_subst.insert(var, def, pr);
}
m_num_steps++;
}
TRACE("gaussian_elim",
tout << "candidate vars:\n";
ptr_vector<app>::iterator it = m_vars.begin();
ptr_vector<app>::iterator end = m_vars.end();
for (; it != end; ++it) {
tout << mk_ismt2_pp(*it, m()) << " ";
}
tout << "\n";);
}
void sort_vars() {
SASSERT(m_candidates.size() == m_vars.size());
TRACE("gaussian_elim_bug", tout << "sorting vars...\n";);
m_ordered_vars.reset();
// The variables (and its definitions) in m_subst must remain alive until the end of this procedure.
// Reason: they are scheduled for unmarking in visiting/done.
// They should remain alive while they are on the stack.
// To make sure this is the case, whenever a variable (and its definition) is removed from m_subst,
// I add them to the saved vector.
expr_ref_vector saved(m());
expr_fast_mark1 visiting;
expr_fast_mark2 done;
typedef std::pair<expr *, unsigned> frame;
svector<frame> todo;
ptr_vector<app>::const_iterator it = m_vars.begin();
ptr_vector<app>::const_iterator end = m_vars.end();
unsigned num;
for (; it != end; ++it) {
checkpoint();
app * v = *it;
if (!m_candidate_vars.is_marked(v))
continue;
todo.push_back(frame(v, 0));
while (!todo.empty()) {
start:
frame & fr = todo.back();
expr * t = fr.first;
m_num_steps++;
TRACE("gaussian_elim_bug", tout << "processing:\n" << mk_ismt2_pp(t, m()) << "\n";);
if (t->get_ref_count() > 1 && done.is_marked(t)) {
todo.pop_back();
continue;
}
switch (t->get_kind()) {
case AST_VAR:
todo.pop_back();
break;
case AST_QUANTIFIER:
num = to_quantifier(t)->get_num_children();
while (fr.second < num) {
expr * c = to_quantifier(t)->get_child(fr.second);
fr.second++;
if (c->get_ref_count() > 1 && done.is_marked(c))
continue;
todo.push_back(frame(c, 0));
goto start;
}
if (t->get_ref_count() > 1)
done.mark(t);
todo.pop_back();
break;
case AST_APP:
num = to_app(t)->get_num_args();
if (num == 0) {
if (fr.second == 0) {
if (m_candidate_vars.is_marked(t)) {
if (visiting.is_marked(t)) {
// cycle detected: remove t
visiting.reset_mark(t);
m_candidate_vars.mark(t, false);
SASSERT(!m_candidate_vars.is_marked(t));
// Must save t and its definition.
// See comment in the beginning of the function
expr * def = 0;
proof * pr;
m_subst.find(to_app(t), def, pr);
SASSERT(def != 0);
saved.push_back(t);
saved.push_back(def);
//
m_subst.erase(t);
}
else {
visiting.mark(t);
fr.second = 1;
expr * def = 0;
proof * pr;
m_subst.find(to_app(t), def, pr);
SASSERT(def != 0);
todo.push_back(frame(def, 0));
goto start;
}
}
}
else {
SASSERT(fr.second == 1);
if (m_candidate_vars.is_marked(t)) {
visiting.reset_mark(t);
m_ordered_vars.push_back(to_app(t));
}
else {
// var was removed from the list of candidate vars to elim cycle
// do nothing
}
}
}
else {
while (fr.second < num) {
expr * arg = to_app(t)->get_arg(fr.second);
fr.second++;
if (arg->get_ref_count() > 1 && done.is_marked(arg))
continue;
todo.push_back(frame(arg, 0));
goto start;
}
}
if (t->get_ref_count() > 1)
done.mark(t);
todo.pop_back();
break;
default:
UNREACHABLE();
todo.pop_back();
break;
}
}
}
// cleanup
it = m_vars.begin();
for (unsigned idx = 0; it != end; ++it, ++idx) {
if (!m_candidate_vars.is_marked(*it)) {
m_candidate_set.mark(m_candidates[idx], false);
}
}
TRACE("gaussian_elim",
tout << "ordered vars:\n";
ptr_vector<app>::iterator it = m_ordered_vars.begin();
ptr_vector<app>::iterator end = m_ordered_vars.end();
for (; it != end; ++it) {
SASSERT(m_candidate_vars.is_marked(*it));
tout << mk_ismt2_pp(*it, m()) << " ";
}
tout << "\n";);
m_candidate_vars.reset();
}
void normalize() {
m_norm_subst.reset();
m_r->set_substitution(&m_norm_subst);
expr_ref new_def(m());
proof_ref new_pr(m());
unsigned size = m_ordered_vars.size();
for (unsigned idx = 0; idx < size; idx++) {
checkpoint();
expr * v = m_ordered_vars[idx];
expr * def = 0;
proof * pr = 0;
m_subst.find(v, def, pr);
SASSERT(def != 0);
m_r->operator()(def, new_def, new_pr);
m_num_steps += m_r->get_num_steps() + 1;
if (m().proofs_enabled())
new_pr = m().mk_transitivity(pr, new_pr);
m_norm_subst.insert(v, new_def, new_pr);
// we updated the substituting, but we don't need to reset m_r
// because all cached values there do not depend on v.
}
m_subst.reset();
TRACE("gaussian_elim",
tout << "after normalizing variables\n";
for (unsigned i = 0; i < m_ordered_vars.size(); i++) {
expr * v = m_ordered_vars[i];
expr * def = 0;
proof * pr = 0;
m_norm_subst.find(v, def, pr);
tout << mk_ismt2_pp(v, m()) << "\n----->\n" << mk_ismt2_pp(def, m()) << "\n\n";
});
#if 0
DEBUG_CODE({
for (unsigned i = 0; i < m_ordered_vars.size(); i++) {
expr * v = m_ordered_vars[i];
expr * def = 0;
proof * pr = 0;
m_norm_subst.find(v, def, pr);
SASSERT(def != 0);
CASSERT("gaussian_elim_bug", !occurs(v, def));
}
});
#endif
}
void substitute(assertion_set & set) {
// force the cache of m_r to be reset.
m_r->set_substitution(&m_norm_subst);
expr_ref new_f(m());
proof_ref new_pr(m());
unsigned size = set.size();
for (unsigned idx = 0; idx < size; idx++) {
checkpoint();
expr * f = set.form(idx);
TRACE("gaussian_leak", tout << "processing:\n" << mk_ismt2_pp(f, m()) << "\n";);
if (m_candidate_set.is_marked(f)) {
// f may be deleted after the following update.
// so, we must remove remove the mark before doing the update
m_candidate_set.mark(f, false);
SASSERT(!m_candidate_set.is_marked(f));
set.update(idx, m().mk_true(), m().mk_true_proof());
m_num_steps ++;
continue;
}
else {
m_r->operator()(f, new_f, new_pr);
}
TRACE("gaussian_elim_subst", tout << mk_ismt2_pp(f, m()) << "\n--->\n" << mk_ismt2_pp(new_f, m()) << "\n";);
m_num_steps += m_r->get_num_steps() + 1;
if (m().proofs_enabled()) {
new_pr = m().mk_modus_ponens(set.pr(idx), new_pr);
}
set.update(idx, new_f, new_pr);
if (set.inconsistent())
return;
}
set.elim_true();
TRACE("gaussian_elim",
tout << "after applying substitution\n";
set.display(tout););
#if 0
DEBUG_CODE({
for (unsigned i = 0; i < m_ordered_vars.size(); i++) {
expr * v = m_ordered_vars[i];
for (unsigned j = 0; j < set.size(); j++) {
CASSERT("gaussian_elim_bug", !occurs(v, set.form(j)));
}
}});
#endif
}
void save_elim_vars(model_converter_ref & mc) {
IF_VERBOSE(100, if (!m_ordered_vars.empty()) verbose_stream() << "num. eliminated vars: " << m_ordered_vars.size() << "\n";);
m_num_eliminated_vars += m_ordered_vars.size();
if (m_produce_models) {
if (mc.get() == 0)
mc = alloc(gmc, m());
ptr_vector<app>::iterator it = m_ordered_vars.begin();
ptr_vector<app>::iterator end = m_ordered_vars.end();
for (; it != end; ++it) {
app * v = *it;
expr * def = 0;
proof * pr;
m_norm_subst.find(v, def, pr);
SASSERT(def != 0);
static_cast<gmc*>(mc.get())->insert(v->get_decl(), def);
}
}
}
void collect_num_occs(expr * t, expr_fast_mark1 & visited) {
ptr_buffer<expr, 128> stack;
#define VISIT(ARG) { \
if (is_uninterp_const(ARG)) { \
obj_map<expr, unsigned>::obj_map_entry * entry = m_num_occs.insert_if_not_there2(ARG, 0); \
entry->get_data().m_value++; \
} \
if (!visited.is_marked(ARG)) { \
visited.mark(ARG, true); \
stack.push_back(ARG); \
} \
}
VISIT(t);
while (!stack.empty()) {
expr * t = stack.back();
stack.pop_back();
if (!is_app(t))
continue;
unsigned j = to_app(t)->get_num_args();
while (j > 0) {
--j;
expr * arg = to_app(t)->get_arg(j);
VISIT(arg);
}
}
}
void collect_num_occs(assertion_set & s) {
if (m_max_occs == UINT_MAX)
return; // no need to compute num occs
m_num_occs.reset();
expr_fast_mark1 visited;
unsigned sz = s.size();
for (unsigned i = 0; i < sz; i++)
collect_num_occs(s.form(i), visited);
}
void operator()(assertion_set & s, model_converter_ref & mc) {
SASSERT(is_well_sorted(s));
as_st_report report("gaussian-elimination", s);
TRACE("gaussian_elim", tout << "starting guassian elimination\n"; s.display(tout); tout << "\n";);
m_num_steps = 0;
mc = 0;
if (s.inconsistent())
return;
while (true) {
collect_num_occs(s);
collect(s);
if (m_subst.empty())
break;
sort_vars();
if (m_ordered_vars.empty())
break;
normalize();
substitute(s);
if (s.inconsistent()) {
mc = 0;
break;
}
save_elim_vars(mc);
TRACE("gaussian_elim_round", s.display(tout); if (mc) mc->display(tout););
}
TRACE("gaussian_elim", s.display(tout););
SASSERT(is_well_sorted(s));
}
void set_cancel(bool f) {
m_cancel = f;
m_r->set_cancel(f);
}
unsigned get_num_steps() const {
return m_num_steps;
}
unsigned get_num_eliminated_vars() const {
return m_num_eliminated_vars;
}
};
gaussian_elim::gaussian_elim(ast_manager & m, params_ref const & p, expr_replacer * r, bool owner):
m_params(p) {
m_imp = alloc(imp, m, p, r, owner);
}
gaussian_elim::~gaussian_elim() {
dealloc(m_imp);
}
ast_manager & gaussian_elim::m() const {
return m_imp->m();
}
void gaussian_elim::updt_params(params_ref const & p) {
m_params = p;
m_imp->updt_params(p);
}
void gaussian_elim::get_param_descrs(param_descrs & r) {
insert_produce_models(r);
r.insert(":gaussian-max-occs", CPK_UINT, "(default: infty) maximum number of occurrences for considering a variable for gaussian eliminations.");
r.insert(":theory-solver", CPK_BOOL, "(default: true) use theory solvers.");
r.insert(":ite-solver", CPK_BOOL, "(default: true) use if-then-else solver.");
}
void gaussian_elim::operator()(assertion_set & s, model_converter_ref & mc) {
m_imp->operator()(s, mc);
report_st_progress(":num-elim-vars", get_num_eliminated_vars());
}
void gaussian_elim::set_cancel(bool f) {
if (m_imp)
m_imp->set_cancel(f);
}
void gaussian_elim::cleanup() {
unsigned num_elim_vars = m_imp->m_num_eliminated_vars;
ast_manager & m = m_imp->m();
imp * d = m_imp;
expr_replacer * r = m_imp->m_r_owner ? m_imp->m_r : 0;
if (r)
r->set_substitution(0);
bool owner = m_imp->m_r_owner;
m_imp->m_r_owner = false; // stole replacer
#pragma omp critical (as_st_cancel)
{
m_imp = 0;
}
dealloc(d);
d = alloc(imp, m, m_params, r, owner);
#pragma omp critical (as_st_cancel)
{
m_imp = d;
}
m_imp->m_num_eliminated_vars = num_elim_vars;
}
unsigned gaussian_elim::get_num_steps() const {
return m_imp->get_num_steps();
}
unsigned gaussian_elim::get_num_eliminated_vars() const {
return m_imp->get_num_eliminated_vars();
}
void gaussian_elim::collect_statistics(statistics & st) const {
st.update("eliminated vars", get_num_eliminated_vars());
}
void gaussian_elim::reset_statistics() {
m_imp->m_num_eliminated_vars = 0;
}
as_st * mk_gaussian(ast_manager & m, params_ref const & p) {
return clean(alloc(gaussian_elim, m, p, mk_expr_simp_replacer(m, p), true));
}

View file

@ -0,0 +1,66 @@
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
gaussian_elim.h
Abstract:
(extended) Gaussian elimination for assertion sets.
It also supports other theories besides arithmetic.
Author:
Leonardo (leonardo) 2011-04-21
Notes:
--*/
#ifndef _GAUSSIAN_ELIM_H_
#define _GAUSSIAN_ELIM_H_
#include"assertion_set_strategy.h"
class expr_replacer;
MK_ST_EXCEPTION(gaussian_elim_exception);
class gaussian_elim : public assertion_set_strategy {
struct imp;
imp * m_imp;
params_ref m_params;
public:
gaussian_elim(ast_manager & m, params_ref const & p = params_ref(), expr_replacer * r = 0, bool owner = false);
virtual ~gaussian_elim();
ast_manager & m () const;
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 gaussian elimination on the assertion set \c s.
Return a model_converter that converts any model for the updated set into a model for the old set.
*/
virtual void operator()(assertion_set & s, model_converter_ref & mc);
virtual void cleanup();
unsigned get_num_steps() const;
unsigned get_num_eliminated_vars() const;
virtual void collect_statistics(statistics & st) const;
virtual void reset_statistics();
protected:
virtual void set_cancel(bool f);
};
as_st * mk_gaussian(ast_manager & m, params_ref const & p = params_ref());
inline as_st * mk_eq_solver(ast_manager & m, params_ref const & p = params_ref()) {
return mk_gaussian(m, p);
}
#endif

View file

@ -0,0 +1,29 @@
/*++
Copyright (c) 2012 Microsoft Corporation
Module Name:
num_occurs_assertion_set.cpp
Abstract:
TODO: delete
Author:
Leonardo de Moura (leonardo) 2012-10-20.
Revision History:
--*/
#include"num_occurs_assertion_set.h"
#include"assertion_set.h"
// TODO delete
void num_occurs_as::operator()(assertion_set const & s) {
expr_fast_mark1 visited;
unsigned sz = s.size();
for (unsigned i = 0; i < sz; i++) {
process(s.form(i), visited);
}
}

View file

@ -0,0 +1,38 @@
/*++
Copyright (c) 2012 Microsoft Corporation
Module Name:
num_occurs_assertion_set.h
Abstract:
TODO: delete
Author:
Leonardo de Moura (leonardo) 2012-10-20.
Revision History:
--*/
#ifndef _NUM_OCCURS_AS_H_
#define _NUM_OCCURS_AS_H_
#include"num_occurs.h"
class assertion_set;
/**
\brief Functor for computing the number of occurrences of each sub-expression in a expression F.
*/
class num_occurs_as : public num_occurs {
public:
num_occurs_as(bool ignore_ref_count1 = false, bool ignore_quantifiers = false):
num_occurs(ignore_ref_count1, ignore_quantifiers) {
}
void operator()(assertion_set const & s); // TODO delete
};
#endif

View file

@ -0,0 +1,521 @@
/*++
Copyright (c) 2006 Microsoft Corporation
Module Name:
reduce_args.cpp
Abstract:
<abstract>
Author:
Leonardo de Moura (leonardo) 2010-04-06.
Revision History:
--*/
#include"reduce_args.h"
#include"cooperate.h"
#include"ast_smt2_pp.h"
#include"map.h"
#include"rewriter_def.h"
#include"elim_var_model_converter.h"
#include"filter_model_converter.h"
struct reduce_args::imp {
ast_manager & m_manager;
bool m_produce_models;
volatile bool m_cancel;
ast_manager & m() const { return m_manager; }
imp(ast_manager & m, params_ref const & p):
m_manager(m) {
updt_params(p);
m_cancel = false;
}
void updt_params(params_ref const & p) {
m_produce_models = p.get_bool(":produce-models", false);
}
void set_cancel(bool f) {
m_cancel = f;
}
void checkpoint() {
if (m_cancel)
throw reduce_args_exception(STE_CANCELED_MSG);
cooperate("reduce-args");
}
struct find_non_candidates_proc {
ast_manager & m_manager;
obj_hashtable<func_decl> & m_non_cadidates;
find_non_candidates_proc(ast_manager & m, obj_hashtable<func_decl> & non_cadidates):
m_manager(m),
m_non_cadidates(non_cadidates) {
}
void operator()(var * n) {}
void operator()(quantifier * n) {}
void operator()(app * n) {
if (n->get_num_args() == 0)
return; // ignore constants
func_decl * d = n->get_decl();
if (d->get_family_id() != null_family_id)
return; // ignore interpreted symbols
if (m_non_cadidates.contains(d))
return; // it is already in the set.
unsigned j = n->get_num_args();
while (j > 0) {
--j;
if (m_manager.is_value(n->get_arg(j)))
return;
}
m_non_cadidates.insert(d);
}
};
/**
\brief Populate the table non_cadidates with function declarations \c f
such that there is a function application (f t1 ... tn) where t1 ... tn are not values.
*/
void find_non_candidates(assertion_set const & s, obj_hashtable<func_decl> & non_candidates) {
non_candidates.reset();
find_non_candidates_proc proc(m_manager, non_candidates);
expr_fast_mark1 visited;
unsigned sz = s.size();
for (unsigned i = 0; i < sz; i++) {
checkpoint();
quick_for_each_expr(proc, visited, s.form(i));
}
TRACE("reduce_args", tout << "non_candidates:\n";
obj_hashtable<func_decl>::iterator it = non_candidates.begin();
obj_hashtable<func_decl>::iterator end = non_candidates.end();
for (; it != end; ++it) {
func_decl * d = *it;
tout << d->get_name() << "\n";
});
}
struct populate_decl2args_proc {
ast_manager & m_manager;
obj_hashtable<func_decl> & m_non_cadidates;
obj_map<func_decl, bit_vector> & m_decl2args;
populate_decl2args_proc(ast_manager & m, obj_hashtable<func_decl> & nc, obj_map<func_decl, bit_vector> & d):
m_manager(m), m_non_cadidates(nc), m_decl2args(d) {}
void operator()(var * n) {}
void operator()(quantifier * n) {}
void operator()(app * n) {
if (n->get_num_args() == 0)
return; // ignore constants
func_decl * d = n->get_decl();
if (d->get_family_id() != null_family_id)
return; // ignore interpreted symbols
if (m_non_cadidates.contains(d))
return; // declaration is not a candidate
unsigned j = n->get_num_args();
obj_map<func_decl, bit_vector>::iterator it = m_decl2args.find_iterator(d);
if (it == m_decl2args.end()) {
m_decl2args.insert(d, bit_vector());
it = m_decl2args.find_iterator(d);
SASSERT(it != m_decl2args.end());
it->m_value.reserve(j);
while (j > 0) {
--j;
it->m_value.set(j, m_manager.is_value(n->get_arg(j)));
}
} else {
SASSERT(j == it->m_value.size());
while (j > 0) {
--j;
it->m_value.set(j, it->m_value.get(j) && m_manager.is_value(n->get_arg(j)));
}
}
}
};
void populate_decl2args(assertion_set const & s,
obj_hashtable<func_decl> & non_candidates,
obj_map<func_decl, bit_vector> & decl2args) {
expr_fast_mark1 visited;
decl2args.reset();
populate_decl2args_proc proc(m_manager, non_candidates, decl2args);
unsigned sz = s.size();
for (unsigned i = 0; i < sz; i++) {
checkpoint();
quick_for_each_expr(proc, visited, s.form(i));
}
// Remove all cases where the simplification is not applicable.
ptr_buffer<func_decl> bad_decls;
obj_map<func_decl, bit_vector>::iterator it = decl2args.begin();
obj_map<func_decl, bit_vector>::iterator end = decl2args.end();
for (; it != end; it++) {
bool is_zero = true;
for (unsigned i = 0; i < it->m_value.size() && is_zero ; i++) {
if (it->m_value.get(i))
is_zero = false;
}
if (is_zero)
bad_decls.push_back(it->m_key);
}
ptr_buffer<func_decl>::iterator it2 = bad_decls.begin();
ptr_buffer<func_decl>::iterator end2 = bad_decls.end();
for (; it2 != end2; ++it2)
decl2args.erase(*it2);
TRACE("reduce_args", tout << "decl2args:" << std::endl;
for (obj_map<func_decl, bit_vector>::iterator it = decl2args.begin() ; it != decl2args.end() ; it++) {
tout << it->m_key->get_name() << ": ";
for (unsigned i = 0 ; i < it->m_value.size() ; i++)
tout << (it->m_value.get(i) ? "1" : "0");
tout << std::endl;
});
}
struct arg2func_hash_proc {
bit_vector const & m_bv;
arg2func_hash_proc(bit_vector const & bv):m_bv(bv) {}
unsigned operator()(app const * n) const {
// compute the hash-code using only the arguments where m_bv is true.
unsigned a = 0x9e3779b9;
unsigned num_args = n->get_num_args();
for (unsigned i = 0; i < num_args; i++) {
if (!m_bv.get(i))
continue; // ignore argument
a = hash_u_u(a, n->get_arg(i)->get_id());
}
return a;
}
};
struct arg2func_eq_proc {
bit_vector const & m_bv;
arg2func_eq_proc(bit_vector const & bv):m_bv(bv) {}
bool operator()(app const * n1, app const * n2) const {
// compare only the arguments where m_bv is true
SASSERT(n1->get_num_args() == n2->get_num_args());
unsigned num_args = n1->get_num_args();
for (unsigned i = 0; i < num_args; i++) {
if (!m_bv.get(i))
continue; // ignore argument
if (n1->get_arg(i) != n2->get_arg(i))
return false;
}
return true;
}
};
typedef map<app *, func_decl *, arg2func_hash_proc, arg2func_eq_proc> arg2func;
typedef obj_map<func_decl, arg2func *> decl2arg2func_map;
struct reduce_args_ctx {
ast_manager & m_manager;
decl2arg2func_map m_decl2arg2funcs;
reduce_args_ctx(ast_manager & m): m_manager(m) {
}
~reduce_args_ctx() {
obj_map<func_decl, arg2func *>::iterator it = m_decl2arg2funcs.begin();
obj_map<func_decl, arg2func *>::iterator end = m_decl2arg2funcs.end();
for (; it != end; ++it) {
arg2func * map = it->m_value;
arg2func::iterator it2 = map->begin();
arg2func::iterator end2 = map->end();
for (; it2 != end2; ++it2) {
m_manager.dec_ref(it2->m_key);
m_manager.dec_ref(it2->m_value);
}
dealloc(map);
}
}
};
struct populate_decl2arg_set_proc {
ast_manager & m_manager;
obj_map<func_decl, bit_vector> & m_decl2args;
decl2arg2func_map & m_decl2arg2funcs;
populate_decl2arg_set_proc(ast_manager & m,
obj_map<func_decl, bit_vector> & d,
decl2arg2func_map & ds):
m_manager(m), m_decl2args(d), m_decl2arg2funcs(ds) {}
void operator()(var * n) {}
void operator()(quantifier * n) {}
void operator()(app * n) {
if (n->get_num_args() == 0)
return; // ignore constants
func_decl * d = n->get_decl();
if (d->get_family_id() != null_family_id)
return; // ignore interpreted symbols
obj_map<func_decl, bit_vector>::iterator it = m_decl2args.find_iterator(d);
if (it == m_decl2args.end())
return; // not reducing the arguments of this declaration
bit_vector & bv = it->m_value;
arg2func * map = 0;
decl2arg2func_map::iterator it2 = m_decl2arg2funcs.find_iterator(d);
if (it2 == m_decl2arg2funcs.end()) {
map = alloc(arg2func, arg2func_hash_proc(bv), arg2func_eq_proc(bv));
m_decl2arg2funcs.insert(d, map);
}
else {
map = it2->m_value;
}
if (!map->contains(n)) {
// create fresh symbol...
ptr_buffer<sort> domain;
unsigned arity = d->get_arity();
for (unsigned i = 0; i < arity; i++) {
if (!bv.get(i))
domain.push_back(d->get_domain(i));
}
func_decl * new_d = m_manager.mk_fresh_func_decl(d->get_name(), symbol::null, domain.size(), domain.c_ptr(), d->get_range());
map->insert(n, new_d);
m_manager.inc_ref(n);
m_manager.inc_ref(new_d);
}
}
};
void populate_decl2arg_set(assertion_set const & s,
obj_map<func_decl, bit_vector> & decl2args,
decl2arg2func_map & decl2arg2funcs) {
expr_fast_mark1 visited;
populate_decl2arg_set_proc proc(m_manager, decl2args, decl2arg2funcs);
unsigned sz = s.size();
for (unsigned i = 0; i < sz; i++) {
checkpoint();
quick_for_each_expr(proc, visited, s.form(i));
}
}
struct reduce_args_rw_cfg : public default_rewriter_cfg {
ast_manager & m;
imp & m_owner;
obj_map<func_decl, bit_vector> & m_decl2args;
decl2arg2func_map & m_decl2arg2funcs;
reduce_args_rw_cfg(imp & owner, obj_map<func_decl, bit_vector> & decl2args, decl2arg2func_map & decl2arg2funcs):
m(owner.m_manager),
m_owner(owner),
m_decl2args(decl2args),
m_decl2arg2funcs(decl2arg2funcs) {
}
bool max_steps_exceeded(unsigned num_steps) const {
m_owner.checkpoint();
return false;
}
br_status reduce_app(func_decl * f, unsigned num, expr * const * args, expr_ref & result, proof_ref & result_pr) {
result_pr = 0;
if (f->get_arity() == 0)
return BR_FAILED; // ignore constants
if (f->get_family_id() != null_family_id)
return BR_FAILED; // ignore interpreted symbols
decl2arg2func_map::iterator it = m_decl2arg2funcs.find_iterator(f);
if (it == m_decl2arg2funcs.end())
return BR_FAILED;
SASSERT(m_decl2args.contains(f));
bit_vector & bv = m_decl2args.find(f);
arg2func * map = it->m_value;
app_ref tmp(m);
tmp = m.mk_app(f, num, args);
CTRACE("reduce_args", !map->contains(tmp),
tout << "map does not contain tmp f: " << f->get_name() << "\n";
tout << mk_ismt2_pp(tmp, m) << "\n";
arg2func::iterator it = map->begin();
arg2func::iterator end = map->end();
for (; it != end; ++it) {
tout << mk_ismt2_pp(it->m_key, m) << "\n---> " << it->m_value->get_name() << "\n";
});
SASSERT(map->contains(tmp));
func_decl * new_f = map->find(tmp);
ptr_buffer<expr> new_args;
for (unsigned i = 0; i < num; i++) {
if (!bv.get(i))
new_args.push_back(args[i]);
}
result = m.mk_app(new_f, new_args.size(), new_args.c_ptr());
return BR_DONE;
}
};
struct reduce_args_rw : rewriter_tpl<reduce_args_rw_cfg> {
reduce_args_rw_cfg m_cfg;
public:
reduce_args_rw(imp & owner, obj_map<func_decl, bit_vector> & decl2args, decl2arg2func_map & decl2arg2funcs):
rewriter_tpl<reduce_args_rw_cfg>(owner.m_manager, false, m_cfg),
m_cfg(owner, decl2args, decl2arg2funcs) {
}
};
model_converter * mk_mc(obj_map<func_decl, bit_vector> & decl2args, decl2arg2func_map & decl2arg2funcs) {
ptr_buffer<expr> new_args;
var_ref_vector new_vars(m_manager);
ptr_buffer<expr> new_eqs;
elim_var_model_converter * e_mc = alloc(elim_var_model_converter, m_manager);
filter_model_converter * f_mc = alloc(filter_model_converter, m_manager);
decl2arg2func_map::iterator it = decl2arg2funcs.begin();
decl2arg2func_map::iterator end = decl2arg2funcs.end();
for (; it != end; ++it) {
func_decl * f = it->m_key;
arg2func * map = it->m_value;
expr * def = 0;
SASSERT(decl2args.contains(f));
bit_vector & bv = decl2args.find(f);
new_vars.reset();
new_args.reset();
for (unsigned i = 0; i < f->get_arity(); i++) {
new_vars.push_back(m_manager.mk_var(i, f->get_domain(i)));
if (!bv.get(i))
new_args.push_back(new_vars.back());
}
arg2func::iterator it2 = map->begin();
arg2func::iterator end2 = map->end();
for (; it2 != end2; ++it2) {
app * t = it2->m_key;
func_decl * new_def = it2->m_value;
f_mc->insert(new_def);
SASSERT(new_def->get_arity() == new_args.size());
app * new_t = m_manager.mk_app(new_def, new_args.size(), new_args.c_ptr());
if (def == 0) {
def = new_t;
}
else {
new_eqs.reset();
for (unsigned i = 0; i < f->get_arity(); i++) {
if (bv.get(i))
new_eqs.push_back(m_manager.mk_eq(new_vars.get(i), t->get_arg(i)));
}
SASSERT(new_eqs.size() > 0);
expr * cond;
if (new_eqs.size() == 1)
cond = new_eqs[0];
else
cond = m_manager.mk_and(new_eqs.size(), new_eqs.c_ptr());
def = m_manager.mk_ite(cond, new_t, def);
}
}
SASSERT(def);
e_mc->insert(f, def);
}
return concat(f_mc, e_mc);
}
void operator()(assertion_set & s, model_converter_ref & mc) {
mc = 0;
if (s.inconsistent())
return;
if (m().proofs_enabled())
throw reduce_args_exception("reduce-args does not support proofs");
as_st_report report("reduce-args", s);
TRACE("reduce_args", s.display(tout););
obj_hashtable<func_decl> non_candidates;
obj_map<func_decl, bit_vector> decl2args;
find_non_candidates(s, non_candidates);
populate_decl2args(s, non_candidates, decl2args);
if (decl2args.empty())
return;
ptr_vector<arg2func> arg2funcs;
reduce_args_ctx ctx(m_manager);
populate_decl2arg_set(s, decl2args, ctx.m_decl2arg2funcs);
reduce_args_rw rw(*this, decl2args, ctx.m_decl2arg2funcs);
unsigned sz = s.size();
for (unsigned i = 0; i < sz; i++) {
if (s.inconsistent())
break;
expr * f = s.form(i);
expr_ref new_f(m_manager);
rw(f, new_f);
s.update(i, new_f);
}
report_st_progress(":reduced-funcs", decl2args.size());
if (m_produce_models)
mc = mk_mc(decl2args, ctx.m_decl2arg2funcs);
TRACE("reduce_args", s.display(tout); if (mc) mc->display(tout););
}
};
reduce_args::reduce_args(ast_manager & m, params_ref const & p):
m_params(p) {
m_imp = alloc(imp, m, p);
}
reduce_args::~reduce_args() {
dealloc(m_imp);
}
ast_manager & reduce_args::m() const {
return m_imp->m();
}
void reduce_args::updt_params(params_ref const & p) {
m_params = p;
m_imp->updt_params(p);
}
void reduce_args::get_param_descrs(param_descrs & r) {
insert_produce_models(r);
}
void reduce_args::operator()(assertion_set & s, model_converter_ref & mc) {
m_imp->operator()(s, mc);
}
void reduce_args::set_cancel(bool f) {
if (m_imp)
m_imp->set_cancel(f);
}
void reduce_args::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;
}
}
void reduce_args::collect_statistics(statistics & st) const {
}
void reduce_args::reset_statistics() {
}
as_st * mk_reduce_args(ast_manager & m, params_ref const & p) {
return clean(alloc(reduce_args, m, p));
}

View file

@ -0,0 +1,92 @@
/*++
Copyright (c) 2006 Microsoft Corporation
Module Name:
reduce_args.h
Abstract:
<abstract>
Author:
Leonardo de Moura (leonardo) 2010-04-05.
Revision History:
Make it a strategy 2011-07-26.
--*/
#ifndef _REDUCE_ARGS_H_
#define _REDUCE_ARGS_H_
#include"assertion_set_strategy.h"
MK_ST_EXCEPTION(reduce_args_exception);
/**
\brief Reduce the number of arguments in function applications.
Example, suppose we have a function f with 2 arguments.
There are 1000 applications of this function, but the first argument is always "a", "b" or "c".
Thus, we replace the f(t1, t2)
with
f_a(t2) if t1 = a
f_b(t2) if t2 = b
f_c(t2) if t2 = c
Since f_a, f_b, f_c are new symbols, satisfiability is preserved.
This transformation is very similar in spirit to the Ackermman's reduction.
This transformation should work in the following way:
1- Create a mapping decl2arg_map from declarations to tuples of booleans, an entry [f -> (true, false, true)]
means that f is a declaration with 3 arguments where the first and third arguments are always values.
2- Traverse the formula and populate the mapping.
For each function application f(t1, ..., tn) do
a) Create a boolean tuple (is_value(t1), ..., is_value(tn)) and do
the logical-and with the tuple that is already in the mapping. If there is no such tuple
in the mapping, we just add a new entry.
If all entries are false-tuples, then there is nothing to be done. The transformation is not applicable.
Now, we create a mapping decl2new_decl from (decl, val_1, ..., val_n) to decls. Note that, n may be different for each entry,
but it is the same for the same declaration.
For example, suppose we have [f -> (true, false, true)] in decl2arg_map, and applications f(1, a, 2), f(1, b, 2), f(1, b, 3), f(2, b, 3), f(2, c, 3) in the formula.
Then, decl2arg_map would contain
(f, 1, 2) -> f_1_2
(f, 1, 3) -> f_1_3
(f, 2, 3) -> f_2_3
where f_1_2, f_1_3 and f_2_3 are new function symbols.
Using the new map, we can replace the occurrences of f.
*/
class reduce_args : public assertion_set_strategy {
struct imp;
imp * m_imp;
params_ref m_params;
public:
reduce_args(ast_manager & m, params_ref const & p = params_ref());
virtual ~reduce_args();
ast_manager & m () const;
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();
virtual void collect_statistics(statistics & st) const;
virtual void reset_statistics();
protected:
virtual void set_cancel(bool f);
};
as_st * mk_reduce_args(ast_manager & m, params_ref const & p = params_ref());
#endif /* _REDUCE_ARGS_H_ */

View file

@ -0,0 +1,791 @@
/*++
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);
}
}
// HACK introduced during code reorg.
// NOTE: the whole file will be deleted.
struct collect_boolean_interface_proc2 {
struct visitor {
obj_hashtable<expr> & m_r;
visitor(obj_hashtable<expr> & r):m_r(r) {}
void operator()(var * n) {}
void operator()(app * n) { if (is_uninterp_const(n)) m_r.insert(n); }
void operator()(quantifier * n) {}
};
ast_manager & m;
expr_fast_mark2 fvisited;
expr_fast_mark1 tvisited;
ptr_vector<expr> todo;
visitor proc;
collect_boolean_interface_proc2(ast_manager & _m, obj_hashtable<expr> & r):
m(_m),
proc(r) {
}
void process(expr * f) {
if (fvisited.is_marked(f))
return;
fvisited.mark(f);
todo.push_back(f);
while (!todo.empty()) {
expr * t = todo.back();
todo.pop_back();
if (is_uninterp_const(t))
continue;
if (is_app(t) && to_app(t)->get_family_id() == m.get_basic_family_id() && to_app(t)->get_num_args() > 0) {
decl_kind k = to_app(t)->get_decl_kind();
if (k == OP_OR || k == OP_NOT || k == OP_IFF || ((k == OP_EQ || k == OP_ITE) && m.is_bool(to_app(t)->get_arg(1)))) {
unsigned num = to_app(t)->get_num_args();
for (unsigned i = 0; i < num; i++) {
expr * arg = to_app(t)->get_arg(i);
if (fvisited.is_marked(arg))
continue;
fvisited.mark(arg);
todo.push_back(arg);
}
}
}
else {
quick_for_each_expr(proc, tvisited, t);
}
}
}
template<typename T>
void operator()(T const & g) {
unsigned sz = g.size();
for (unsigned i = 0; i < sz; i++)
process(g.form(i));
}
void operator()(unsigned sz, expr * const * fs) {
for (unsigned i = 0; i < sz; i++)
process(fs[i]);
}
};
template<typename T>
void collect_boolean_interface_core2(T const & s, obj_hashtable<expr> & r) {
collect_boolean_interface_proc2 proc(s.m(), r);
proc(s);
}
void collect_boolean_interface(assertion_set const & s, obj_hashtable<expr> & r) {
collect_boolean_interface_core2(s, r);
}

View file

@ -0,0 +1,98 @@
/*++
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"
class assertion_set; // TODO: delete
void collect_boolean_interface(assertion_set const & s, obj_hashtable<expr> & r);
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

View file

@ -0,0 +1,187 @@
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
sat_solver_strategy.cpp
Abstract:
Strategy for using the SAT solver preprocessing capabilities.
Author:
Leonardo (leonardo) 2011-05-23
Notes:
--*/
#include"sat_solver_strategy.h"
#include"assertion_set2sat.h"
#include"sat_solver.h"
#include"filter_model_converter.h"
#include"ast_smt2_pp.h"
#include"model_v2_pp.h"
struct sat_solver_strategy::imp {
ast_manager & m;
assertion_set2sat m_as2sat;
sat2assertion_set m_sat2as;
sat::solver m_solver;
params_ref m_params;
bool m_produce_models;
imp(ast_manager & _m, params_ref const & p):
m(_m),
m_solver(p, 0),
m_params(p) {
SASSERT(!m.proofs_enabled());
m_produce_models = p.get_bool(":produce-models", false);
}
void operator()(assertion_set & s, model_converter_ref & mc) {
if (s.m().proofs_enabled())
throw sat::solver_exception("sat solver does not support proofs");
TRACE("before_sat_solver", s.display(tout););
s.elim_redundancies();
if (s.inconsistent()) {
mc = 0;
return;
}
atom2bool_var map(m);
m_as2sat(s, m_params, m_solver, map);
TRACE("sat_solver_unknown", tout << "interpreted_atoms: " << map.interpreted_atoms() << "\n";
atom2bool_var::iterator it = map.begin();
atom2bool_var::iterator end = map.end();
for (; it != end; ++it) {
if (!is_uninterp_const(it->m_key))
tout << mk_ismt2_pp(it->m_key, m) << "\n";
});
s.reset();
s.m().compact_memory();
CASSERT("sat_solver", m_solver.check_invariant());
IF_VERBOSE(ST_VERBOSITY_LVL, m_solver.display_status(verbose_stream()););
TRACE("sat_dimacs", m_solver.display_dimacs(tout););
lbool r = m_solver.check();
if (r == l_false) {
mc = 0;
s.reset();
s.assert_expr(m.mk_false(), 0);
return;
}
else if (r == l_true && !map.interpreted_atoms()) {
// register model
model_ref md = alloc(model, m);
sat::model const & ll_m = m_solver.get_model();
TRACE("sat_solver_strategy", for (unsigned i = 0; i < ll_m.size(); i++) tout << i << ":" << ll_m[i] << " "; tout << "\n";);
atom2bool_var::iterator it = map.begin();
atom2bool_var::iterator end = map.end();
for (; it != end; ++it) {
expr * n = it->m_key;
sat::bool_var v = it->m_value;
TRACE("sat_solver_strategy", tout << "extracting value of " << mk_ismt2_pp(n, m) << "\nvar: " << v << "\n";);
switch (sat::value_at(v, ll_m)) {
case l_true:
md->register_decl(to_app(n)->get_decl(), m.mk_true());
break;
case l_false:
md->register_decl(to_app(n)->get_decl(), m.mk_false());
break;
default:
break;
}
}
s.reset();
TRACE("sat_solver_strategy", model_v2_pp(tout, *md););
mc = model2model_converter(md.get());
}
else {
// get simplified problem.
#if 0
IF_VERBOSE(ST_VERBOSITY_LVL, verbose_stream() << "\"formula constains interpreted atoms, recovering formula from sat solver...\"\n";);
#endif
m_solver.pop(m_solver.scope_lvl());
m_sat2as(m_solver, map, m_params, s, mc);
}
}
void set_cancel(bool f) {
m_as2sat.set_cancel(f);
m_sat2as.set_cancel(f);
m_solver.set_cancel(f);
}
};
sat_solver_strategy::sat_solver_strategy(ast_manager & m, params_ref const & p):
m_imp(0),
m_params(p) {
}
sat_solver_strategy::~sat_solver_strategy() {
SASSERT(m_imp == 0);
}
void sat_solver_strategy::updt_params(params_ref const & p) {
m_params = p;
}
void sat_solver_strategy::get_param_descrs(param_descrs & r) {
assertion_set2sat::collect_param_descrs(r);
sat2assertion_set::collect_param_descrs(r);
sat::solver::collect_param_descrs(r);
insert_produce_models(r);
}
struct sat_solver_strategy::scoped_set_imp {
sat_solver_strategy * m_owner;
scoped_set_imp(sat_solver_strategy * o, sat_solver_strategy::imp * i):m_owner(o) {
#pragma omp critical (sat_solver_strategy)
{
m_owner->m_imp = i;
}
}
~scoped_set_imp() {
#pragma omp critical (sat_solver_strategy)
{
m_owner->m_imp = 0;
}
}
};
void sat_solver_strategy::operator()(assertion_set & s, model_converter_ref & mc) {
imp proc(s.m(), m_params);
scoped_set_imp set(this, &proc);
try {
proc(s, mc);
proc.m_solver.collect_statistics(m_stats);
}
catch (sat::solver_exception & ex) {
proc.m_solver.collect_statistics(m_stats);
throw ex;
}
TRACE("sat_stats", m_stats.display_smt2(tout););
}
void sat_solver_strategy::cleanup() {
SASSERT(m_imp == 0);
}
void sat_solver_strategy::set_cancel(bool f) {
#pragma omp critical (sat_solver_strategy)
{
if (m_imp)
m_imp->set_cancel(f);
}
}
void sat_solver_strategy::reset_statistics() {
m_stats.reset();
}
void sat_solver_strategy::collect_statistics(statistics & st) const {
st.copy(m_stats);
}

View file

@ -0,0 +1,65 @@
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
sat_solver_strategy.h
Abstract:
Strategy for using the SAT solver.
If the assertion set contains theory atoms, then the sat solver just
checks whether the boolean abstraction is satisfiable or not.
Author:
Leonardo (leonardo) 2011-06-02
Notes:
--*/
#ifndef _SAT_SOLVER_STRATEGY_H_
#define _SAT_SOLVER_STRATEGY_H_
#include"assertion_set_strategy.h"
class assertion_set;
class sat_solver_strategy : public assertion_set_strategy {
struct imp;
imp * m_imp;
params_ref m_params;
statistics m_stats;
struct scoped_set_imp;
public:
sat_solver_strategy(ast_manager & m, params_ref const & p = params_ref());
virtual ~sat_solver_strategy();
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();
virtual void collect_statistics(statistics & st) const;
virtual void reset_statistics();
protected:
virtual void set_cancel(bool f);
};
inline as_st * mk_sat_solver(ast_manager & m, params_ref const & p = params_ref()) {
return clean(alloc(sat_solver_strategy, m, p));
}
// Apply only simplification procedures
inline as_st * mk_sat_preprocessor(ast_manager & m, params_ref const & p = params_ref()) {
params_ref p_aux;
p_aux.set_uint(":max-conflicts", 0);
as_st * st = clean(using_params(mk_sat_solver(m), p_aux));
st->updt_params(p);
return st;
}
#endif

View file

@ -0,0 +1,257 @@
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
shallow_context_simplifier.h
Abstract:
Depth 1 context simplifier.
Author:
Leonardo de Moura (leonardo) 2011-04-28
Revision History:
--*/
#include"shallow_context_simplifier.h"
#include"assertion_set_util.h"
#include"expr_substitution.h"
#include"th_rewriter.h"
#include"ast_smt2_pp.h"
#include"assertion_set_util.h"
struct shallow_context_simplifier::imp {
ast_manager & m_manager;
th_rewriter m_r;
expr_substitution m_subst;
assertion_set * m_set;
as_shared_occs m_occs;
unsigned m_idx;
unsigned m_num_steps;
unsigned m_max_rounds;
bool m_modified;
imp(ast_manager & m, params_ref const & p):
m_manager(m),
m_r(m, p),
m_subst(m),
m_set(0),
m_occs(m, true /* track atoms */) {
m_r.set_substitution(&m_subst);
updt_params_core(p);
}
void updt_params_core(params_ref const & p) {
m_max_rounds = p.get_uint(":max-rounds", 4);
}
void updt_params(params_ref const & p) {
m_r.updt_params(p);
updt_params_core(p);
}
ast_manager & m() const { return m_manager; }
void set_cancel(bool f) {
m_r.set_cancel(f);
}
void reset() {
m_subst.reset();
m_set = 0;
m_num_steps = 0;
}
void push_result(expr * new_curr, proof * new_pr) {
if (m().proofs_enabled()) {
proof * pr = m_set->pr(m_idx);
new_pr = m().mk_modus_ponens(pr, new_pr);
}
m_set->update(m_idx, new_curr, new_pr);
if (is_shared(new_curr)) {
m_subst.insert(new_curr, m().mk_true(), m().mk_iff_true(new_pr));
}
expr * atom;
if (is_shared_neg(new_curr, atom)) {
m_subst.insert(atom, m().mk_false(), m().mk_iff_false(new_pr));
}
expr * lhs, * value;
if (is_shared_eq(new_curr, lhs, value)) {
TRACE("shallow_context_simplifier_bug", tout << "found eq:\n" << mk_ismt2_pp(new_curr, m()) << "\n";);
m_subst.insert(lhs, value, new_pr);
}
}
void process_current() {
expr * curr = m_set->form(m_idx);
expr_ref new_curr(m());
proof_ref new_pr(m());
if (!m_subst.empty()) {
m_r(curr, new_curr, new_pr);
m_num_steps += m_r.get_num_steps();
}
else {
new_curr = curr;
if (m().proofs_enabled())
new_pr = m().mk_reflexivity(curr);
}
TRACE("shallow_context_simplifier_bug", tout << mk_ismt2_pp(curr, m()) << "\n---->\n" << mk_ismt2_pp(new_curr, m()) << "\n";);
push_result(new_curr, new_pr);
if (new_curr != curr)
m_modified = true;
}
void operator()(assertion_set & s) {
SASSERT(is_well_sorted(s));
as_st_report report("shallow-context-simplifier", s);
m_num_steps = 0;
if (s.inconsistent())
return;
SASSERT(m_set == 0);
bool forward = true;
m_set = &s;
m_occs(*m_set);
TRACE("shallow_context_simplifier_bug", m_occs.display(tout, m()); );
unsigned size = s.size();
m_idx = 0;
m_modified = false;
expr_ref new_curr(m());
proof_ref new_pr(m());
unsigned round = 0;
while (true) {
TRACE("shallow_context_simplifier_round", s.display(tout););
if (forward) {
for (; m_idx < size; m_idx++) {
process_current();
if (m_set->inconsistent())
goto end;
}
if (m_subst.empty() && !m_modified)
goto end;
m_occs(*m_set);
m_idx = m_set->size();
forward = false;
m_subst.reset();
m_r.set_substitution(&m_subst); // reset, but keep substitution
}
else {
while (m_idx > 0) {
m_idx--;
process_current();
if (m_set->inconsistent())
goto end;
}
if (!m_modified)
goto end;
m_subst.reset();
m_r.set_substitution(&m_subst); // reset, but keep substitution
m_modified = false;
m_occs(*m_set);
m_idx = 0;
size = m_set->size();
forward = true;
}
round++;
if (round >= m_max_rounds)
break;
IF_VERBOSE(100, verbose_stream() << "starting new round, assertion-set size: " << m_set->num_exprs() << std::endl;);
TRACE("shallow_context_simplifier", tout << "round finished\n"; m_set->display(tout); tout << "\n";);
}
end:
m_set = 0;
SASSERT(is_well_sorted(s));
}
bool is_shared(expr * t) {
return m_occs.is_shared(t);
}
bool is_shared_neg(expr * t, expr * & atom) {
if (!m().is_not(t))
return false;
atom = to_app(t)->get_arg(0);
return is_shared(atom);
}
bool is_shared_eq(expr * t, expr * & lhs, expr * & value) {
if (!m().is_eq(t))
return false;
expr * arg1 = to_app(t)->get_arg(0);
expr * arg2 = to_app(t)->get_arg(1);
if (m().is_value(arg1) && is_shared(arg2)) {
lhs = arg2;
value = arg1;
return true;
}
if (m().is_value(arg2) && is_shared(arg1)) {
lhs = arg1;
value = arg2;
return true;
}
return false;
}
unsigned get_num_steps() const { return m_num_steps; }
};
shallow_context_simplifier::shallow_context_simplifier(ast_manager & m, params_ref const & p):
m_params(p) {
m_imp = alloc(imp, m, p);
}
shallow_context_simplifier::~shallow_context_simplifier() {
dealloc(m_imp);
}
void shallow_context_simplifier::updt_params(params_ref const & p) {
m_params = p;
m_imp->updt_params(p);
}
void shallow_context_simplifier::get_param_descrs(param_descrs & r) {
th_rewriter::get_param_descrs(r);
r.insert(":max-rounds", CPK_UINT, "(default: 2) maximum number of rounds.");
}
void shallow_context_simplifier::operator()(assertion_set & s) {
m_imp->operator()(s);
}
void shallow_context_simplifier::set_cancel(bool f) {
if (m_imp)
m_imp->set_cancel(f);
}
void shallow_context_simplifier::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 shallow_context_simplifier::get_num_steps() const {
return m_imp->get_num_steps();
}

View file

@ -0,0 +1,59 @@
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
shallow_context_simplifier.h
Abstract:
Depth 1 context simplifier.
Author:
Leonardo de Moura (leonardo) 2011-04-28
Revision History:
--*/
#ifndef _SHALLOW_CONTEXT_SIMPLIFIER_H_
#define _SHALLOW_CONTEXT_SIMPLIFIER_H_
#include"assertion_set_strategy.h"
class shallow_context_simplifier : public assertion_set_strategy {
struct imp;
imp * m_imp;
params_ref m_params;
public:
shallow_context_simplifier(ast_manager & m, params_ref const & p = params_ref());
virtual ~shallow_context_simplifier();
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); }
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;
protected:
virtual void set_cancel(bool f);
};
inline as_st * mk_shallow_simplifier(ast_manager & m, params_ref const & p = params_ref()) {
return clean(alloc(shallow_context_simplifier, m, p));
}
inline as_st * mk_constant_propagation(ast_manager & m, params_ref const & p = params_ref()) {
return mk_shallow_simplifier(m, p);
}
#endif

View file

@ -0,0 +1,77 @@
/*++
Copyright (c) 2012 Microsoft Corporation
Module Name:
st2tactic.h
Abstract:
Temporary adapter that converts a assertion_set_strategy into a tactic.
Author:
Leonardo (leonardo) 2012-02-19
Notes:
--*/
#include"assertion_set_strategy.h"
#include"tactic.h"
class st2tactic_wrapper : public tactic {
assertion_set_strategy * m_st;
params_ref m_params;
public:
st2tactic_wrapper(assertion_set_strategy * st):m_st(st) {}
~st2tactic_wrapper() { dealloc(m_st); }
virtual tactic * translate(ast_manager & m) {
// st2tactic_wrapper is a temporary hack to support the old strategy framework.
// This class will be deleted in the future.
UNREACHABLE();
NOT_IMPLEMENTED_YET();
return 0;
}
virtual void operator()(goal_ref const & g, goal_ref_buffer & result, model_converter_ref & mc, proof_converter_ref & pc, expr_dependency_ref & core) {
SASSERT(g->is_well_sorted());
pc = 0; mc = 0; core = 0;
fail_if_unsat_core_generation("st2tactic", g);
assertion_set s(g->m());
for (unsigned i = 0; i < g->size(); i++)
s.assert_expr(g->form(i), g->pr(i));
if (g->models_enabled()) {
params_ref mp = m_params;
mp.set_bool(":produce-models", true);
m_st->updt_params(mp);
}
try {
(*m_st)(s, mc);
}
catch (strategy_exception & ex) {
throw tactic_exception(ex.msg());
}
g->reset();
for (unsigned i = 0; i < s.size(); i++) {
g->assert_expr(s.form(i), s.pr(i), 0);
}
g->inc_depth();
result.push_back(g.get());
SASSERT(g->is_well_sorted());
}
virtual void updt_params(params_ref const & p) { m_params = p; m_st->updt_params(p); }
virtual void collect_param_descrs(param_descrs & r) { m_st->collect_param_descrs(r); }
virtual void cleanup() { m_st->cleanup(); }
virtual void set_cancel(bool f) { m_st->set_cancel(f); }
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 set_logic(symbol const & l) { m_st->set_logic(l); }
virtual void set_progress_callback(progress_callback * callback) { m_st->set_progress_callback(callback); }
};
tactic * st2tactic(assertion_set_strategy * st) {
return alloc(st2tactic_wrapper, st);
}

View file

@ -0,0 +1,27 @@
/*++
Copyright (c) 2012 Microsoft Corporation
Module Name:
st2tactic.h
Abstract:
Temporary adapter that converts a assertion_set_strategy into a tactic.
Author:
Leonardo (leonardo) 2012-02-19
Notes:
--*/
#ifndef _ST2TACTIC_H_
#define _ST2TACTIC_H_
class tactic;
class assertion_set_strategy;
tactic * st2tactic(assertion_set_strategy * st);
#endif

View file

@ -0,0 +1,26 @@
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
strategy_exception.cpp
Abstract:
Strategy exception
Author:
Leonardo (leonardo) 2011-05-02
Notes:
--*/
#include"strategy_exception.h"
char const * strategy_exception::g_ste_canceled_msg = "canceled";
char const * strategy_exception::g_ste_max_memory_msg = "max. memory exceeded";
char const * strategy_exception::g_ste_max_scopes_msg = "max. scopes exceeded";
char const * strategy_exception::g_ste_max_steps_msg = "max. steps exceeded";
char const * strategy_exception::g_ste_max_frames_msg = "max. frames exceeded";
char const * strategy_exception::g_ste_no_proofs_msg = "strategy does not support proof generation";

View file

@ -0,0 +1,53 @@
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
strategy_exception.h
Abstract:
Strategy exception
Author:
Leonardo (leonardo) 2011-05-02
Notes:
--*/
#ifndef _STRATEGY_EXCEPTION_H_
#define _STRATEGY_EXCEPTION_H_
#include"z3_exception.h"
class strategy_exception : public z3_exception {
public:
static char const * g_ste_canceled_msg;
static char const * g_ste_max_memory_msg;
static char const * g_ste_max_scopes_msg;
static char const * g_ste_max_steps_msg;
static char const * g_ste_max_frames_msg;
static char const * g_ste_no_proofs_msg;
protected:
char const * m_msg;
public:
strategy_exception(char const * msg):m_msg(msg) {}
virtual ~strategy_exception() {}
virtual char const * msg() const { return m_msg; }
};
#define STE_CANCELED_MSG strategy_exception::g_ste_canceled_msg
#define STE_MAX_MEMORY_MSG strategy_exception::g_ste_max_memory_msg
#define STE_MAX_SCOPES_MSG strategy_exception::g_ste_max_scopes_msg
#define STE_MAX_STEPS_MSG strategy_exception::g_ste_max_steps_msg
#define STE_MAX_FRAMES_MSG strategy_exception::g_ste_max_frames_msg
#define STE_NO_PROOF_GEN_MSG strategy_exception::g_ste_no_proofs_msg
#define MK_ST_EXCEPTION(NAME) \
class NAME : public strategy_exception { \
public: \
NAME(char const * msg):strategy_exception(msg) {} \
}
#endif

224
src/ast/act_cache.cpp Normal file
View 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
src/ast/act_cache.h Normal file
View 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

View file

@ -0,0 +1,586 @@
/*++
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: return m_r_div_decl;
case OP_IDIV: 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));
}
static bool use_coercion(decl_kind k) {
return k == OP_ADD || k == OP_SUB || k == OP_MUL || k == OP_POWER || k == OP_LE || k == OP_GE || k == OP_LT || k == OP_GT || k == OP_UMINUS;
}
static bool has_real_arg(unsigned arity, sort * const * domain, sort * real_sort) {
for (unsigned i = 0; i < arity; i++)
if (domain[i] == real_sort)
return true;
return false;
}
static bool has_real_arg(ast_manager * m, unsigned num_args, expr * const * args, sort * real_sort) {
for (unsigned i = 0; i < num_args; i++)
if (m->get_sort(args[i]) == real_sort)
return true;
return false;
}
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;
}
if (m_manager->int_real_coercions() && use_coercion(k)) {
return mk_func_decl(fix_kind(k, arity), has_real_arg(arity, domain, m_real_decl));
}
else {
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;
}
if (m_manager->int_real_coercions() && use_coercion(k)) {
return mk_func_decl(fix_kind(k, num_args), has_real_arg(m_manager, num_args, args, m_real_decl));
}
else {
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
src/ast/arith_decl_plugin.h Normal file
View 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_ */

View file

@ -0,0 +1,570 @@
/*++
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, &param);
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, &param);
//
// 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;
}
ptr_buffer<sort> new_domain; // we need this because of coercions.
new_domain.push_back(s);
for (unsigned i = 0; i + 1 < num_parameters; ++i) {
if (!parameters[i].is_ast() ||
!is_sort(parameters[i].get_ast()) ||
!m_manager->compatible_sorts(domain[i+1], to_sort(parameters[i].get_ast()))) {
m_manager->raise_exception("domain sort and parameter do not match");
UNREACHABLE();
return 0;
}
new_domain.push_back(to_sort(parameters[i].get_ast()));
}
SASSERT(new_domain.size() == arity);
return m_manager->mk_func_decl(m_select_sym, arity, new_domain.c_ptr(), 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;
}
ptr_buffer<sort> new_domain; // we need this because of coercions.
new_domain.push_back(s);
for (unsigned i = 0; i < num_parameters; ++i) {
if (!parameters[i].is_ast() || !is_sort(parameters[i].get_ast())) {
m_manager->raise_exception("expecting sort parameter");
return 0;
}
if (!m_manager->compatible_sorts(to_sort(parameters[i].get_ast()), domain[i+1])) {
m_manager->raise_exception("domain sort and parameter do not match");
UNREACHABLE();
return 0;
}
new_domain.push_back(to_sort(parameters[i].get_ast()));
}
SASSERT(new_domain.size() == arity);
return m_manager->mk_func_decl(m_store_sym, arity, new_domain.c_ptr(), 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, &param));
}
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, &param);
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, &param);
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
src/ast/array_decl_plugin.h Normal file
View 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, &param, 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_ */

View file

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

View file

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

View file

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

View file

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

Some files were not shown because too many files have changed in this diff Show more