3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-22 16:45:31 +00:00

Reorganizing the code

Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
Leonardo de Moura 2012-10-21 14:16:35 -07:00
parent 3003ee5cb6
commit dcf778a287
120 changed files with 10 additions and 4 deletions

1812
src/aig/aig.cpp Normal file

File diff suppressed because it is too large Load diff

85
src/aig/aig.h Normal file
View file

@ -0,0 +1,85 @@
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
aig.h
Abstract:
And-inverted graphs
Author:
Leonardo (leonardo) 2011-05-13
Notes:
--*/
#ifndef _AIG_H_
#define _AIG_H_
#include"ast.h"
#include"tactic_exception.h"
class assertion_set;
class goal;
class aig_lit;
class aig_manager;
class aig_exception : public tactic_exception {
public:
aig_exception(char const * msg):tactic_exception(msg) {}
};
class aig_ref {
friend class aig_lit;
friend class aig_manager;
aig_manager * m_manager;
void * m_ref;
aig_ref(aig_manager & m, aig_lit const & l);
public:
aig_ref();
~aig_ref();
aig_ref & operator=(aig_ref const & r);
bool operator==(aig_ref const & r) const { return m_ref == r.m_ref; }
bool operator!=(aig_ref const & r) const { return m_ref != r.m_ref; }
};
class aig_manager {
struct imp;
imp * m_imp;
friend class aig_ref;
public:
// If default_gate_encoding == true, then
// ite(a, b, c) is encoded as (NOT a OR b) AND (a OR c)
// iff(a, b) is encoded as (NOT a OR b) AND (a OR NOT b)
//
// If default_gate_encoding == false, then
// ite(a, b, c) is encoded as (a AND b) OR (NOT a AND c)
// iff(a, b) is encoded as (a AND b) OR (NOT a AND NOT b)
aig_manager(ast_manager & m, unsigned long long max_memory = UINT64_MAX, bool default_gate_encoding = true);
~aig_manager();
void set_max_memory(unsigned long long max);
aig_ref mk_aig(expr * n);
aig_ref mk_aig(assertion_set const & s); // TODO delete
aig_ref mk_aig(goal const & g);
aig_ref mk_not(aig_ref const & r);
aig_ref mk_and(aig_ref const & r1, aig_ref const & r2);
aig_ref mk_or(aig_ref const & r1, aig_ref const & r2);
aig_ref mk_iff(aig_ref const & r1, aig_ref const & r2);
aig_ref mk_ite(aig_ref const & r1, aig_ref const & r2, aig_ref const & r3);
void max_sharing(aig_ref & r);
void to_formula(aig_ref const & r, assertion_set & s); // TODO delete
void to_formula(aig_ref const & r, expr_ref & result);
void to_formula(aig_ref const & r, goal & result);
void to_cnf(aig_ref const & r, goal & result);
void display(std::ostream & out, aig_ref const & r) const;
void display_smt2(std::ostream & out, aig_ref const & r) const;
unsigned get_num_aigs() const;
void cancel() { set_cancel(true); }
void reset_cancel() { set_cancel(false); }
void set_cancel(bool f);
};
#endif

126
src/aig/aig_tactic.cpp Normal file
View file

@ -0,0 +1,126 @@
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
aig_tactic.cpp
Abstract:
Tactic for minimizing circuits using AIGs.
Author:
Leonardo (leonardo) 2011-10-24
Notes:
--*/
#include"tactical.h"
#include"aig.h"
class aig_manager;
class aig_tactic : public tactic {
unsigned long long m_max_memory;
bool m_aig_gate_encoding;
bool m_aig_per_assertion;
aig_manager * m_aig_manager;
struct mk_aig_manager {
aig_tactic & m_owner;
mk_aig_manager(aig_tactic & o, ast_manager & m):m_owner(o) {
aig_manager * mng = alloc(aig_manager, m, o.m_max_memory, o.m_aig_gate_encoding);
#pragma omp critical (aig_tactic)
{
m_owner.m_aig_manager = mng;
}
}
~mk_aig_manager() {
aig_manager * mng = m_owner.m_aig_manager;
#pragma omp critical (aig_tactic)
{
m_owner.m_aig_manager = 0;
}
dealloc(mng);
}
};
public:
aig_tactic(params_ref const & p = params_ref()):m_aig_manager(0) {
updt_params(p);
}
virtual tactic * translate(ast_manager & m) {
aig_tactic * t = alloc(aig_tactic);
t->m_max_memory = m_max_memory;
t->m_aig_gate_encoding = m_aig_gate_encoding;
t->m_aig_per_assertion = m_aig_per_assertion;
return t;
}
virtual void updt_params(params_ref const & p) {
m_max_memory = megabytes_to_bytes(p.get_uint(":max-memory", UINT_MAX));
m_aig_gate_encoding = p.get_bool(":aig-default-gate-encoding", true);
m_aig_per_assertion = p.get_bool(":aig-per-assertion", true);
}
virtual void collect_param_descrs(param_descrs & r) {
insert_max_memory(r);
r.insert(":aig-per-assertion", CPK_BOOL, "(default: true) process one assertion at a time.");
}
void operator()(goal_ref const & g) {
SASSERT(g->is_well_sorted());
tactic_report report("aig", *g);
mk_aig_manager mk(*this, g->m());
if (m_aig_per_assertion) {
unsigned size = g->size();
for (unsigned i = 0; i < size; i++) {
aig_ref r = m_aig_manager->mk_aig(g->form(i));
m_aig_manager->max_sharing(r);
expr_ref new_f(g->m());
m_aig_manager->to_formula(r, new_f);
g->update(i, new_f, 0, g->dep(i));
}
}
else {
fail_if_unsat_core_generation("aig", g);
aig_ref r = m_aig_manager->mk_aig(*(g.get()));
g->reset(); // save memory
m_aig_manager->max_sharing(r);
m_aig_manager->to_formula(r, *(g.get()));
}
SASSERT(g->is_well_sorted());
}
virtual void operator()(goal_ref const & g,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
fail_if_proof_generation("aig", g);
mc = 0; pc = 0; core = 0;
operator()(g);
g->inc_depth();
result.push_back(g.get());
}
virtual void cleanup() {}
protected:
virtual void set_cancel(bool f) {
#pragma omp critical (aig_tactic)
{
if (m_aig_manager)
m_aig_manager->set_cancel(f);
}
}
};
tactic * mk_aig_tactic(params_ref const & p) {
return clean(alloc(aig_tactic, p));
}

27
src/aig/aig_tactic.h Normal file
View file

@ -0,0 +1,27 @@
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
aig_tactic.h
Abstract:
Tactic for minimizing circuits using AIGs.
Author:
Leonardo (leonardo) 2011-10-24
Notes:
--*/
#ifndef _AIG_TACTIC_H_
#define _AIG_TACTIC_H_
#include"params.h"
class tactic;
tactic * mk_aig_tactic(params_ref const & p = params_ref());
#endif

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

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

@ -0,0 +1,571 @@
/*++
Copyright (c) 2012 Microsoft Corporation
Module Name:
api_context.cpp
Abstract:
Interface of Z3 with "external world".
It was called _Z3_context
Author:
Leonardo de Moura (leonardo) 2012-02-29.
Revision History:
--*/
#include"api_context.h"
#include"api_config_params.h"
#include"smtparser.h"
#include"version.h"
#include"ast_pp.h"
#include"ast_ll_pp.h"
#include"api_log_macros.h"
#include"api_util.h"
#include"install_tactics.h"
namespace api {
static void default_error_handler(Z3_context, Z3_error_code c) {
printf("Error: %s\n", Z3_get_error_msg(c));
exit(1);
}
Z3_search_failure mk_Z3_search_failure(smt::failure f) {
switch(f) {
case smt::OK: return Z3_NO_FAILURE;
case smt::UNKNOWN: return Z3_UNKNOWN;
case smt::TIMEOUT: return Z3_TIMEOUT;
case smt::MEMOUT: return Z3_MEMOUT_WATERMARK;
case smt::CANCELED: return Z3_CANCELED;
case smt::NUM_CONFLICTS: return Z3_NUM_CONFLICTS;
case smt::THEORY: return Z3_THEORY;
case smt::QUANTIFIERS: return Z3_QUANTIFIERS;
default:
UNREACHABLE();
break;
}
return static_cast<Z3_search_failure>(f);
}
context::param_ini::param_ini(front_end_params & p) : m_params(p) {
p.open_trace_file();
}
context::param_ini::~param_ini() {
m_params.close_trace_file();
}
context::add_plugins::add_plugins(ast_manager & m) {
m.register_decl_plugins();
}
// ------------------------
//
// Core
//
// ------------------------
context::set_interruptable::set_interruptable(context & ctx, event_handler & i):
m_ctx(ctx) {
#pragma omp critical (set_interruptable)
{
SASSERT(m_ctx.m_interruptable == 0);
m_ctx.m_interruptable = &i;
}
}
context::set_interruptable::~set_interruptable() {
#pragma omp critical (set_interruptable)
{
m_ctx.m_interruptable = 0;
}
}
context::context(config_params * p, bool user_ref_count):
m_params(p ? p->m_params : front_end_params()),
m_param_ini(m_params),
m_user_ref_count(user_ref_count),
m_manager(m_params.m_proof_mode, m_params.m_trace_stream),
m_plugins(m_manager),
m_arith_util(m_manager),
m_bv_util(m_manager),
m_datalog_util(m_manager),
m_last_result(m_manager),
m_ast_trail(m_manager),
m_replay_stack() {
m_solver = 0;
m_error_code = Z3_OK;
m_print_mode = Z3_PRINT_SMTLIB_FULL;
m_searching = false;
m_interruptable = 0;
m_smtlib_parser = 0;
m_smtlib_parser_has_decls = false;
z3_bound_num_procs();
//
// Configuration parameter settings.
//
memory::set_high_watermark(static_cast<size_t>(m_params.m_memory_high_watermark)*1024*1024);
memory::set_max_size(static_cast<size_t>(m_params.m_memory_max_size)*1024*1024);
if (m_params.m_debug_ref_count) {
m_manager.debug_ref_count();
}
m_error_handler = &default_error_handler;
m_basic_fid = m_manager.get_basic_family_id();
m_arith_fid = m_manager.get_family_id("arith");
m_bv_fid = m_manager.get_family_id("bv");
m_array_fid = m_manager.get_family_id("array");
m_dt_fid = m_manager.get_family_id("datatype");
m_datalog_fid = m_manager.get_family_id("datalog_relation");
m_dt_plugin = static_cast<datatype_decl_plugin*>(m_manager.get_plugin(m_dt_fid));
if (!m_user_ref_count) {
m_replay_stack.push_back(0);
}
install_tactics(*this);
}
context::~context() {
m_last_obj = 0;
if (!m_user_ref_count) {
for (unsigned i = 0; i < m_replay_stack.size(); ++i) {
dealloc(m_replay_stack[i]);
}
}
reset_parser();
dealloc(m_solver);
}
void context::interrupt() {
#pragma omp critical (set_interruptable)
{
if (m_interruptable)
(*m_interruptable)();
}
}
void context::set_error_code(Z3_error_code err) {
m_error_code = err;
if (err != Z3_OK)
invoke_error_handler(err);
}
void context::check_searching() {
if (m_searching) {
set_error_code(Z3_INVALID_USAGE); // TBD: error code could be fixed.
}
}
char * context::mk_external_string(char const * str) {
m_string_buffer = str;
return const_cast<char *>(m_string_buffer.c_str());
}
char * context::mk_external_string(std::string const & str) {
m_string_buffer = str;
return const_cast<char *>(m_string_buffer.c_str());
}
expr * context::mk_numeral_core(rational const & n, sort * s) {
expr* e = 0;
family_id fid = s->get_family_id();
if (fid == m_arith_fid) {
e = m_arith_util.mk_numeral(n, s);
}
else if (fid == m_bv_fid) {
e = m_bv_util.mk_numeral(n, s);
}
else if (fid == get_datalog_fid() && n.is_uint64()) {
uint64 sz;
if (m_datalog_util.try_get_size(s, sz) &&
sz <= n.get_uint64()) {
invoke_error_handler(Z3_INVALID_ARG);
}
e = m_datalog_util.mk_numeral(n.get_uint64(), s);
}
else {
invoke_error_handler(Z3_INVALID_ARG);
}
save_ast_trail(e);
return e;
}
expr * context::mk_and(unsigned num_exprs, expr * const * exprs) {
switch(num_exprs) {
case 0:
return m_manager.mk_true();
case 1:
save_ast_trail(exprs[0]);
return exprs[0];
default: {
expr * a = m_manager.mk_and(num_exprs, exprs);
save_ast_trail(a);
return a;
} }
}
void context::persist_ast(ast * n, unsigned num_scopes) {
// persist_ast is irrelevant when m_user_ref_count == true
if (m_user_ref_count)
return;
if (num_scopes > m_ast_lim.size()) {
num_scopes = m_ast_lim.size();
}
SASSERT(m_replay_stack.size() > num_scopes);
unsigned j = m_replay_stack.size() - num_scopes - 1;
if (!m_replay_stack[j]) {
m_replay_stack[j] = alloc(ast_ref_vector, m_manager);
}
m_replay_stack[j]->push_back(n);
}
void context::save_ast_trail(ast * n) {
SASSERT(m().contains(n));
if (m_user_ref_count) {
// Corner case bug: n may be in m_last_result, and this is the only reference to n.
// When, we execute reset() it is deleted
// To avoid this bug, I bump the reference counter before reseting m_last_result
m().inc_ref(n);
m_last_result.reset();
m_last_result.push_back(n);
m().dec_ref(n);
}
else {
m_ast_trail.push_back(n);
}
}
void context::save_multiple_ast_trail(ast * n) {
if (m_user_ref_count)
m_last_result.push_back(n);
else
m_ast_trail.push_back(n);
}
void context::reset_last_result() {
if (m_user_ref_count)
m_last_result.reset();
m_last_obj = 0;
}
void context::save_object(object * r) {
m_last_obj = r;
}
void context::handle_exception(z3_exception & ex) {
if (ex.has_error_code()) {
switch(ex.error_code()) {
case ERR_MEMOUT:
set_error_code(Z3_MEMOUT_FAIL);
break;
case ERR_PARSER:
set_error_code(Z3_PARSER_ERROR);
break;
case ERR_INI_FILE:
set_error_code(Z3_INVALID_ARG);
break;
case ERR_OPEN_FILE:
set_error_code(Z3_FILE_ACCESS_ERROR);
break;
default:
set_error_code(Z3_INTERNAL_FATAL);
break;
}
}
else {
m_exception_msg = ex.msg();
set_error_code(Z3_EXCEPTION);
}
}
void context::invoke_error_handler(Z3_error_code c) {
if (m_error_handler) {
if (g_z3_log) {
// error handler can do crazy stuff such as longjmp
g_z3_log_enabled = true;
}
m_error_handler(reinterpret_cast<Z3_context>(this), c);
}
}
void context::check_sorts(ast * n) {
if (!m().check_sorts(n)) {
switch(n->get_kind()) {
case AST_APP: {
std::ostringstream buffer;
app * a = to_app(n);
buffer << mk_pp(a->get_decl(), m()) << " applied to: ";
if (a->get_num_args() > 1) buffer << "\n";
for (unsigned i = 0; i < a->get_num_args(); ++i) {
buffer << mk_bounded_pp(a->get_arg(i), m(), 3) << " of sort ";
buffer << mk_pp(m().get_sort(a->get_arg(i)), m()) << "\n";
}
warning_msg("%s",buffer.str().c_str());
break;
}
case AST_VAR:
case AST_QUANTIFIER:
case AST_SORT:
case AST_FUNC_DECL:
break;
}
set_error_code(Z3_SORT_ERROR);
}
}
// ------------------------
//
// Solver interface for backward compatibility
//
// ------------------------
smt::solver & context::get_solver() {
if (!m_solver) {
m_solver = alloc(smt::solver, m_manager, m_params);
}
return *m_solver;
}
void context::assert_cnstr(expr * a) {
get_solver().assert_expr(a);
}
lbool context::check(model_ref & m) {
flet<bool> searching(m_searching, true);
lbool r;
r = get_solver().check();
if (r != l_false)
get_solver().get_model(m);
return r;
}
void context::push() {
get_solver().push();
if (!m_user_ref_count) {
m_ast_lim.push_back(m_ast_trail.size());
m_replay_stack.push_back(0);
}
}
void context::pop(unsigned num_scopes) {
for (unsigned i = 0; i < num_scopes; ++i) {
if (!m_user_ref_count) {
unsigned sz = m_ast_lim.back();
m_ast_lim.pop_back();
dealloc(m_replay_stack.back());
m_replay_stack.pop_back();
while (m_ast_trail.size() > sz) {
m_ast_trail.pop_back();
}
}
}
get_solver().pop(num_scopes);
}
// ------------------------
//
// Parser interface for backward compatibility
//
// ------------------------
void context::reset_parser() {
if (m_smtlib_parser) {
dealloc(m_smtlib_parser);
m_smtlib_parser = 0;
m_smtlib_parser_has_decls = false;
m_smtlib_parser_decls.reset();
m_smtlib_parser_sorts.reset();
}
SASSERT(!m_smtlib_parser_has_decls);
}
void context::extract_smtlib_parser_decls() {
if (m_smtlib_parser) {
if (!m_smtlib_parser_has_decls) {
smtlib::symtable * table = m_smtlib_parser->get_benchmark()->get_symtable();
table->get_func_decls(m_smtlib_parser_decls);
table->get_sorts(m_smtlib_parser_sorts);
m_smtlib_parser_has_decls = true;
}
}
else {
m_smtlib_parser_decls.reset();
m_smtlib_parser_sorts.reset();
}
}
};
// ------------------------
//
// Context creation API
//
// ------------------------
extern "C" {
Z3_context Z3_API Z3_mk_context(Z3_config c) {
LOG_Z3_mk_context(c);
memory::initialize(0);
Z3_context r = reinterpret_cast<Z3_context>(alloc(api::context, reinterpret_cast<api::config_params*>(c), false));
RETURN_Z3(r);
}
Z3_context Z3_API Z3_mk_context_rc(Z3_config c) {
LOG_Z3_mk_context_rc(c);
memory::initialize(0);
Z3_context r = reinterpret_cast<Z3_context>(alloc(api::context, reinterpret_cast<api::config_params*>(c), true));
RETURN_Z3(r);
}
void Z3_API Z3_del_context(Z3_context c) {
Z3_TRY;
LOG_Z3_del_context(c);
RESET_ERROR_CODE();
dealloc(mk_c(c));
Z3_CATCH;
}
void Z3_API Z3_interrupt(Z3_context c) {
Z3_TRY;
LOG_Z3_interrupt(c);
mk_c(c)->interrupt();
Z3_CATCH;
}
void Z3_API Z3_toggle_warning_messages(Z3_bool enabled) {
LOG_Z3_toggle_warning_messages(enabled);
enable_warning_messages(enabled != 0);
}
void Z3_API Z3_inc_ref(Z3_context c, Z3_ast a) {
Z3_TRY;
LOG_Z3_inc_ref(c, a);
RESET_ERROR_CODE();
mk_c(c)->m().inc_ref(to_ast(a));
Z3_CATCH;
}
void Z3_API Z3_dec_ref(Z3_context c, Z3_ast a) {
Z3_TRY;
LOG_Z3_dec_ref(c, a);
RESET_ERROR_CODE();
if (to_ast(a)->get_ref_count() == 0) {
SET_ERROR_CODE(Z3_DEC_REF_ERROR);
return;
}
mk_c(c)->m().dec_ref(to_ast(a));
Z3_CATCH;
}
Z3_bool Z3_API Z3_set_logic(Z3_context c, Z3_string logic) {
Z3_TRY;
LOG_Z3_set_logic(c, logic);
RESET_ERROR_CODE();
return mk_c(c)->get_solver().set_logic(symbol(logic));
Z3_CATCH_RETURN(Z3_FALSE);
}
void Z3_API Z3_get_version(unsigned * major,
unsigned * minor,
unsigned * build_number,
unsigned * revision_number) {
LOG_Z3_get_version(major, minor, build_number, revision_number);
*major = Z3_MAJOR_VERSION;
*minor = Z3_MINOR_VERSION;
*build_number = Z3_BUILD_NUMBER;
*revision_number = Z3_REVISION_NUMBER;
}
void Z3_API Z3_reset_memory(void) {
LOG_Z3_reset_memory();
memory::finalize();
memory::initialize(0);
}
Z3_error_code Z3_API Z3_get_error_code(Z3_context c) {
LOG_Z3_get_error_code(c);
return mk_c(c)->get_error_code();
}
void Z3_API Z3_set_error_handler(Z3_context c, Z3_error_handler h) {
RESET_ERROR_CODE();
mk_c(c)->set_error_handler(h);
// [Leo]: using exception handling, we don't need global error handlers anymore
}
void Z3_API Z3_set_error(__in Z3_context c, __in Z3_error_code e) {
SET_ERROR_CODE(e);
}
static char const * _get_error_msg_ex(Z3_context c, Z3_error_code err) {
switch(err) {
case Z3_OK: return "ok";
case Z3_SORT_ERROR: return "type error";
case Z3_IOB: return "index out of bounds";
case Z3_INVALID_ARG: return "invalid argument";
case Z3_PARSER_ERROR: return "parser error";
case Z3_NO_PARSER: return "parser (data) is not available";
case Z3_INVALID_PATTERN: return "invalid pattern";
case Z3_MEMOUT_FAIL: return "out of memory";
case Z3_FILE_ACCESS_ERROR: return "file access error";
case Z3_INTERNAL_FATAL: return "internal error";
case Z3_INVALID_USAGE: return "invalid usage";
case Z3_DEC_REF_ERROR: return "invalid dec_ref command";
case Z3_EXCEPTION: return c == 0 ? "Z3 exception" : mk_c(c)->get_exception_msg();
default: return "unknown";
}
}
char const * Z3_API Z3_get_error_msg(Z3_error_code err) {
LOG_Z3_get_error_msg(err);
return _get_error_msg_ex(0, err);
}
char const * Z3_API Z3_get_error_msg_ex(Z3_context c, Z3_error_code err) {
LOG_Z3_get_error_msg_ex(c, err);
return _get_error_msg_ex(c, err);
}
void Z3_API Z3_persist_ast(Z3_context c, Z3_ast n, unsigned num_scopes) {
Z3_TRY;
LOG_Z3_persist_ast(c, n, num_scopes);
RESET_ERROR_CODE();
CHECK_VALID_AST(to_ast(n), );
mk_c(c)->persist_ast(to_ast(n), num_scopes);
Z3_CATCH;
}
void Z3_API Z3_set_ast_print_mode(Z3_context c, Z3_ast_print_mode mode) {
Z3_TRY;
LOG_Z3_set_ast_print_mode(c, mode);
RESET_ERROR_CODE();
mk_c(c)->set_print_mode(mode);
Z3_CATCH;
}
};
ast_manager & Z3_API Z3_get_manager(__in Z3_context c) {
return mk_c(c)->m();
}
front_end_params& Z3_API Z3_get_parameters(__in Z3_context c) {
return mk_c(c)->fparams();
}
Z3_context Z3_mk_context_from_params(front_end_params const& p) {
api::config_params cp(p);
return reinterpret_cast<Z3_context>(alloc(api::context, &cp));
}

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

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

@ -0,0 +1,322 @@
/*++
Copyright (c) 2012 Microsoft Corporation
Module Name:
api_solver.cpp
Abstract:
New solver API
Author:
Leonardo de Moura (leonardo) 2012-03-07.
Revision History:
--*/
#include<iostream>
#include"z3.h"
#include"api_log_macros.h"
#include"api_context.h"
#include"api_tactic.h"
#include"api_solver.h"
#include"api_model.h"
#include"api_stats.h"
#include"api_ast_vector.h"
#include"tactic2solver.h"
#include"scoped_ctrl_c.h"
#include"cancel_eh.h"
#include"scoped_timer.h"
#include"smt_strategic_solver.h"
extern "C" {
Z3_solver Z3_API Z3_mk_simple_solver(Z3_context c) {
Z3_TRY;
LOG_Z3_mk_simple_solver(c);
RESET_ERROR_CODE();
Z3_solver_ref * s = alloc(Z3_solver_ref);
s->m_solver = mk_default_solver();
s->m_solver->set_front_end_params(mk_c(c)->fparams());
s->m_solver->init(mk_c(c)->m(), symbol::null);
mk_c(c)->save_object(s);
Z3_solver r = of_solver(s);
RETURN_Z3(r);
Z3_CATCH_RETURN(0);
}
Z3_solver Z3_API Z3_mk_solver(Z3_context c) {
Z3_TRY;
LOG_Z3_mk_solver(c);
RESET_ERROR_CODE();
Z3_solver_ref * s = alloc(Z3_solver_ref);
s->m_solver = mk_smt_strategic_solver();
s->m_solver->set_front_end_params(mk_c(c)->fparams());
s->m_solver->init(mk_c(c)->m(), symbol::null);
mk_c(c)->save_object(s);
Z3_solver r = of_solver(s);
RETURN_Z3(r);
Z3_CATCH_RETURN(0);
}
Z3_solver Z3_API Z3_mk_solver_for_logic(Z3_context c, Z3_symbol logic) {
Z3_TRY;
LOG_Z3_mk_solver_for_logic(c, logic);
RESET_ERROR_CODE();
Z3_solver_ref * s = alloc(Z3_solver_ref);
s->m_solver = mk_smt_strategic_solver(true /* force solver to use tactics even when auto_config is disabled */);
s->m_solver->set_front_end_params(mk_c(c)->fparams());
s->m_solver->init(mk_c(c)->m(), to_symbol(logic));
mk_c(c)->save_object(s);
Z3_solver r = of_solver(s);
RETURN_Z3(r);
Z3_CATCH_RETURN(0);
}
Z3_solver Z3_API Z3_mk_solver_from_tactic(Z3_context c, Z3_tactic t) {
Z3_TRY;
LOG_Z3_mk_solver_from_tactic(c, t);
RESET_ERROR_CODE();
Z3_solver_ref * s = alloc(Z3_solver_ref);
s->m_solver = alloc(tactic2solver_api, to_tactic_ref(t));
s->m_solver->set_front_end_params(mk_c(c)->fparams());
s->m_solver->init(mk_c(c)->m(), symbol::null);
mk_c(c)->save_object(s);
Z3_solver r = of_solver(s);
RETURN_Z3(r);
Z3_CATCH_RETURN(0);
}
Z3_string Z3_API Z3_solver_get_help(Z3_context c, Z3_solver s) {
Z3_TRY;
LOG_Z3_solver_get_help(c, s);
RESET_ERROR_CODE();
std::ostringstream buffer;
param_descrs descrs;
to_solver_ref(s)->collect_param_descrs(descrs);
descrs.display(buffer);
return mk_c(c)->mk_external_string(buffer.str());
Z3_CATCH_RETURN("");
}
Z3_param_descrs Z3_API Z3_solver_get_param_descrs(Z3_context c, Z3_solver s) {
Z3_TRY;
LOG_Z3_solver_get_param_descrs(c, s);
RESET_ERROR_CODE();
Z3_param_descrs_ref * d = alloc(Z3_param_descrs_ref);
mk_c(c)->save_object(d);
to_solver_ref(s)->collect_param_descrs(d->m_descrs);
Z3_param_descrs r = of_param_descrs(d);
RETURN_Z3(r);
Z3_CATCH_RETURN(0);
}
void Z3_API Z3_solver_set_params(Z3_context c, Z3_solver s, Z3_params p) {
Z3_TRY;
LOG_Z3_solver_set_params(c, s, p);
RESET_ERROR_CODE();
to_solver_ref(s)->updt_params(to_param_ref(p));
to_solver(s)->m_params = to_param_ref(p);
Z3_CATCH;
}
void Z3_API Z3_solver_inc_ref(Z3_context c, Z3_solver s) {
Z3_TRY;
LOG_Z3_solver_inc_ref(c, s);
RESET_ERROR_CODE();
to_solver(s)->inc_ref();
Z3_CATCH;
}
void Z3_API Z3_solver_dec_ref(Z3_context c, Z3_solver s) {
Z3_TRY;
LOG_Z3_solver_dec_ref(c, s);
RESET_ERROR_CODE();
to_solver(s)->dec_ref();
Z3_CATCH;
}
void Z3_API Z3_solver_push(Z3_context c, Z3_solver s) {
Z3_TRY;
LOG_Z3_solver_push(c, s);
RESET_ERROR_CODE();
to_solver_ref(s)->push();
Z3_CATCH;
}
void Z3_API Z3_solver_pop(Z3_context c, Z3_solver s, unsigned n) {
Z3_TRY;
LOG_Z3_solver_pop(c, s, n);
RESET_ERROR_CODE();
if (n > to_solver_ref(s)->get_scope_level()) {
SET_ERROR_CODE(Z3_IOB);
return;
}
if (n > 0)
to_solver_ref(s)->pop(n);
Z3_CATCH;
}
void Z3_API Z3_solver_reset(Z3_context c, Z3_solver s) {
Z3_TRY;
LOG_Z3_solver_reset(c, s);
RESET_ERROR_CODE();
to_solver_ref(s)->reset();
to_solver_ref(s)->init(mk_c(c)->m(), symbol::null);
Z3_CATCH;
}
unsigned Z3_API Z3_solver_get_num_scopes(Z3_context c, Z3_solver s) {
Z3_TRY;
LOG_Z3_solver_get_num_scopes(c, s);
RESET_ERROR_CODE();
return to_solver_ref(s)->get_scope_level();
Z3_CATCH_RETURN(0);
}
void Z3_API Z3_solver_assert(Z3_context c, Z3_solver s, Z3_ast a) {
Z3_TRY;
LOG_Z3_solver_assert(c, s, a);
RESET_ERROR_CODE();
CHECK_FORMULA(a,);
to_solver_ref(s)->assert_expr(to_expr(a));
Z3_CATCH;
}
Z3_ast_vector Z3_API Z3_solver_get_assertions(Z3_context c, Z3_solver s) {
Z3_TRY;
LOG_Z3_solver_get_assertions(c, s);
RESET_ERROR_CODE();
Z3_ast_vector_ref * v = alloc(Z3_ast_vector_ref, mk_c(c)->m());
mk_c(c)->save_object(v);
unsigned sz = to_solver_ref(s)->get_num_assertions();
for (unsigned i = 0; i < sz; i++) {
v->m_ast_vector.push_back(to_solver_ref(s)->get_assertion(i));
}
RETURN_Z3(of_ast_vector(v));
Z3_CATCH_RETURN(0);
}
static Z3_lbool _solver_check(Z3_context c, Z3_solver s, unsigned num_assumptions, Z3_ast const assumptions[]) {
for (unsigned i = 0; i < num_assumptions; i++) {
if (!is_expr(to_ast(assumptions[i]))) {
SET_ERROR_CODE(Z3_INVALID_ARG);
return Z3_L_UNDEF;
}
}
expr * const * _assumptions = to_exprs(assumptions);
to_solver_ref(s)->set_produce_models(to_solver(s)->m_params.get_bool(":model", true));
to_solver_ref(s)->set_produce_proofs(mk_c(c)->m().proofs_enabled());
to_solver_ref(s)->set_produce_unsat_cores(num_assumptions > 0);
unsigned timeout = to_solver(s)->m_params.get_uint(":timeout", UINT_MAX);
bool use_ctrl_c = to_solver(s)->m_params.get_bool(":ctrl-c", false);
cancel_eh<solver> eh(*to_solver_ref(s));
api::context::set_interruptable(*(mk_c(c)), eh);
lbool result;
{
scoped_ctrl_c ctrlc(eh, false, use_ctrl_c);
scoped_timer timer(timeout, &eh);
try {
result = to_solver_ref(s)->check_sat(num_assumptions, _assumptions);
}
catch (z3_exception & ex) {
mk_c(c)->handle_exception(ex);
return Z3_L_UNDEF;
}
}
return static_cast<Z3_lbool>(result);
}
Z3_lbool Z3_API Z3_solver_check(Z3_context c, Z3_solver s) {
Z3_TRY;
LOG_Z3_solver_check(c, s);
RESET_ERROR_CODE();
return _solver_check(c, s, 0, 0);
Z3_CATCH_RETURN(Z3_L_UNDEF);
}
Z3_lbool Z3_API Z3_solver_check_assumptions(Z3_context c, Z3_solver s, unsigned num_assumptions, Z3_ast const assumptions[]) {
Z3_TRY;
LOG_Z3_solver_check_assumptions(c, s, num_assumptions, assumptions);
RESET_ERROR_CODE();
return _solver_check(c, s, num_assumptions, assumptions);
Z3_CATCH_RETURN(Z3_L_UNDEF);
}
Z3_model Z3_API Z3_solver_get_model(Z3_context c, Z3_solver s) {
Z3_TRY;
LOG_Z3_solver_get_model(c, s);
RESET_ERROR_CODE();
model_ref _m;
to_solver_ref(s)->get_model(_m);
if (!_m) {
SET_ERROR_CODE(Z3_INVALID_USAGE);
RETURN_Z3(0);
}
Z3_model_ref * m_ref = alloc(Z3_model_ref);
m_ref->m_model = _m;
mk_c(c)->save_object(m_ref);
RETURN_Z3(of_model(m_ref));
Z3_CATCH_RETURN(0);
}
Z3_ast Z3_API Z3_solver_get_proof(Z3_context c, Z3_solver s) {
Z3_TRY;
LOG_Z3_solver_get_proof(c, s);
RESET_ERROR_CODE();
proof * p = to_solver_ref(s)->get_proof();
if (!p) {
SET_ERROR_CODE(Z3_INVALID_USAGE);
RETURN_Z3(0);
}
mk_c(c)->save_ast_trail(p);
RETURN_Z3(of_ast(p));
Z3_CATCH_RETURN(0);
}
Z3_ast_vector Z3_API Z3_solver_get_unsat_core(Z3_context c, Z3_solver s) {
Z3_TRY;
LOG_Z3_solver_get_unsat_core(c, s);
RESET_ERROR_CODE();
ptr_vector<expr> core;
to_solver_ref(s)->get_unsat_core(core);
Z3_ast_vector_ref * v = alloc(Z3_ast_vector_ref, mk_c(c)->m());
mk_c(c)->save_object(v);
for (unsigned i = 0; i < core.size(); i++) {
v->m_ast_vector.push_back(core[i]);
}
RETURN_Z3(of_ast_vector(v));
Z3_CATCH_RETURN(0);
}
Z3_string Z3_API Z3_solver_get_reason_unknown(Z3_context c, Z3_solver s) {
Z3_TRY;
LOG_Z3_solver_get_reason_unknown(c, s);
RESET_ERROR_CODE();
return mk_c(c)->mk_external_string(to_solver_ref(s)->reason_unknown());
Z3_CATCH_RETURN("");
}
Z3_stats Z3_API Z3_solver_get_statistics(Z3_context c, Z3_solver s) {
Z3_TRY;
LOG_Z3_solver_get_statistics(c, s);
RESET_ERROR_CODE();
Z3_stats_ref * st = alloc(Z3_stats_ref);
to_solver_ref(s)->collect_statistics(st->m_stats);
mk_c(c)->save_object(st);
Z3_stats r = of_stats(st);
RETURN_Z3(r);
Z3_CATCH_RETURN(0);
}
Z3_string Z3_API Z3_solver_to_string(Z3_context c, Z3_solver s) {
Z3_TRY;
LOG_Z3_solver_to_string(c, s);
RESET_ERROR_CODE();
std::ostringstream buffer;
to_solver_ref(s)->display(buffer);
return mk_c(c)->mk_external_string(buffer.str());
Z3_CATCH_RETURN("");
}
};

35
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,164 @@
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
add_bounds.h
Abstract:
Strategy for bounding unbounded variables.
Author:
Leonardo de Moura (leonardo) 2011-06-30.
Revision History:
--*/
#include"add_bounds.h"
#include"arith_decl_plugin.h"
#include"ast_smt2_pp.h"
#include"bound_manager.h"
#include"for_each_expr.h"
#include"assertion_set_util.h"
struct is_unbounded_proc {
struct found {};
arith_util m_util;
bound_manager & m_bm;
is_unbounded_proc(bound_manager & bm):m_util(bm.m()), m_bm(bm) {}
void operator()(app * t) {
if (is_uninterp_const(t) && (m_util.is_int(t) || m_util.is_real(t)) && (!m_bm.has_lower(t) || !m_bm.has_upper(t)))
throw found();
}
void operator()(var *) {}
void operator()(quantifier*) {}
};
bool is_unbounded(assertion_set const & s) {
ast_manager & m = s.m();
bound_manager bm(m);
bm(s);
is_unbounded_proc proc(bm);
return test(s, proc);
}
struct add_bounds::imp {
ast_manager & m;
rational m_lower;
rational m_upper;
volatile bool m_cancel;
imp(ast_manager & _m, params_ref const & p):
m(_m) {
updt_params(p);
}
void updt_params(params_ref const & p) {
m_lower = p.get_rat(":add-bound-lower", rational(-2));
m_upper = p.get_rat(":add-bound-upper", rational(2));
}
void set_cancel(bool f) {
m_cancel = f;
}
struct add_bound_proc {
arith_util m_util;
bound_manager & m_bm;
assertion_set & m_set;
rational const & m_lower;
rational const & m_upper;
unsigned m_num_bounds;
add_bound_proc(bound_manager & bm, assertion_set & s, rational const & l, rational const & u):
m_util(bm.m()),
m_bm(bm),
m_set(s),
m_lower(l),
m_upper(u) {
m_num_bounds = 0;
}
void operator()(app * t) {
if (is_uninterp_const(t) && (m_util.is_int(t) || m_util.is_real(t))) {
if (!m_bm.has_lower(t)) {
m_set.assert_expr(m_util.mk_le(t, m_util.mk_numeral(m_upper, m_util.is_int(t))));
m_num_bounds++;
}
if (!m_bm.has_upper(t)) {
m_set.assert_expr(m_util.mk_ge(t, m_util.mk_numeral(m_lower, m_util.is_int(t))));
m_num_bounds++;
}
}
}
void operator()(var *) {}
void operator()(quantifier*) {}
};
void operator()(assertion_set & s, model_converter_ref & mc) {
mc = 0;
if (s.inconsistent())
return;
as_st_report report("add-bounds", s);
bound_manager bm(m);
expr_fast_mark1 visited;
add_bound_proc proc(bm, s, m_lower, m_upper);
unsigned sz = s.size();
for (unsigned i = 0; i < sz; i++)
quick_for_each_expr(proc, visited, s.form(i));
visited.reset();
report_st_progress(":added-bounds", proc.m_num_bounds);
TRACE("add_bounds", s.display(tout););
}
};
add_bounds::add_bounds(ast_manager & m, params_ref const & p):
m_params(p) {
m_imp = alloc(imp, m, p);
}
add_bounds::~add_bounds() {
dealloc(m_imp);
}
void add_bounds::updt_params(params_ref const & p) {
m_params = p;
m_imp->updt_params(p);
}
void add_bounds::get_param_descrs(param_descrs & r) {
r.insert(":add-bound-lower", CPK_NUMERAL, "(default: -2) lower bound to be added to unbounded variables.");
r.insert(":add-bound-upper", CPK_NUMERAL, "(default: 2) upper bound to be added to unbounded variables.");
}
void add_bounds::operator()(assertion_set & s, model_converter_ref & mc) {
m_imp->operator()(s, mc);
}
void add_bounds::set_cancel(bool f) {
if (m_imp)
m_imp->set_cancel(f);
}
void add_bounds::cleanup() {
ast_manager & m = m_imp->m;
imp * d = m_imp;
#pragma omp critical (as_st_cancel)
{
d = m_imp;
}
dealloc(d);
d = alloc(imp, m, m_params);
#pragma omp critical (as_st_cancel)
{
m_imp = d;
}
}

View file

@ -0,0 +1,50 @@
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
add_bounds.h
Abstract:
Strategy for bounding unbounded variables.
Author:
Leonardo de Moura (leonardo) 2011-06-30.
Revision History:
--*/
#ifndef _ADD_BOUNDS_H_
#define _ADD_BOUNDS_H_
#include"assertion_set_strategy.h"
bool is_unbounded(assertion_set const & s);
class add_bounds : public assertion_set_strategy {
struct imp;
imp * m_imp;
params_ref m_params;
public:
add_bounds(ast_manager & m, params_ref const & p = params_ref());
virtual ~add_bounds();
virtual void updt_params(params_ref const & p);
static void get_param_descrs(param_descrs & r);
virtual void collect_param_descrs(param_descrs & r) { get_param_descrs(r); }
virtual void operator()(assertion_set & s, model_converter_ref & mc);
virtual void cleanup();
protected:
virtual void set_cancel(bool f);
};
inline as_st * mk_add_bounds(ast_manager & m, params_ref const & p = params_ref()) {
return clean(alloc(add_bounds, m, p));
}
#endif

View file

@ -0,0 +1,198 @@
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
add_bounds_tactic.h
Abstract:
Tactic for bounding unbounded variables.
Author:
Leonardo de Moura (leonardo) 2011-10-22.
Revision History:
--*/
#include"tactical.h"
#include"arith_decl_plugin.h"
#include"ast_smt2_pp.h"
#include"bound_manager.h"
struct is_unbounded_proc {
struct found {};
arith_util m_util;
bound_manager & m_bm;
is_unbounded_proc(bound_manager & bm):m_util(bm.m()), m_bm(bm) {}
void operator()(app * t) {
if (is_uninterp_const(t) && (m_util.is_int(t) || m_util.is_real(t)) && (!m_bm.has_lower(t) || !m_bm.has_upper(t)))
throw found();
}
void operator()(var *) {}
void operator()(quantifier*) {}
};
bool is_unbounded(goal const & g) {
ast_manager & m = g.m();
bound_manager bm(m);
bm(g);
is_unbounded_proc proc(bm);
return test(g, proc);
}
class is_unbounded_probe : public probe {
public:
virtual result operator()(goal const & g) {
return is_unbounded(g);
}
};
probe * mk_is_unbounded_probe() {
return alloc(is_unbounded_probe);
}
class add_bounds_tactic : public tactic {
struct imp {
ast_manager & m;
rational m_lower;
rational m_upper;
volatile bool m_cancel;
imp(ast_manager & _m, params_ref const & p):
m(_m) {
updt_params(p);
}
void updt_params(params_ref const & p) {
m_lower = p.get_rat(":add-bound-lower", rational(-2));
m_upper = p.get_rat(":add-bound-upper", rational(2));
}
void set_cancel(bool f) {
m_cancel = f;
}
struct add_bound_proc {
arith_util m_util;
bound_manager & m_bm;
goal & m_goal;
rational const & m_lower;
rational const & m_upper;
unsigned m_num_bounds;
add_bound_proc(bound_manager & bm, goal & g, rational const & l, rational const & u):
m_util(bm.m()),
m_bm(bm),
m_goal(g),
m_lower(l),
m_upper(u) {
m_num_bounds = 0;
}
void operator()(app * t) {
if (is_uninterp_const(t) && (m_util.is_int(t) || m_util.is_real(t))) {
if (!m_bm.has_lower(t)) {
m_goal.assert_expr(m_util.mk_le(t, m_util.mk_numeral(m_upper, m_util.is_int(t))));
m_num_bounds++;
}
if (!m_bm.has_upper(t)) {
m_goal.assert_expr(m_util.mk_ge(t, m_util.mk_numeral(m_lower, m_util.is_int(t))));
m_num_bounds++;
}
}
}
void operator()(var *) {}
void operator()(quantifier*) {}
};
virtual void operator()(goal_ref const & g,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
mc = 0; pc = 0; core = 0;
tactic_report report("add-bounds", *g);
bound_manager bm(m);
expr_fast_mark1 visited;
add_bound_proc proc(bm, *(g.get()), m_lower, m_upper);
unsigned sz = g->size();
for (unsigned i = 0; i < sz; i++)
quick_for_each_expr(proc, visited, g->form(i));
visited.reset();
g->inc_depth();
result.push_back(g.get());
if (proc.m_num_bounds > 0)
g->updt_prec(goal::UNDER);
report_tactic_progress(":added-bounds", proc.m_num_bounds);
TRACE("add_bounds", g->display(tout););
}
};
imp * m_imp;
params_ref m_params;
public:
add_bounds_tactic(ast_manager & m, params_ref const & p):
m_params(p) {
m_imp = alloc(imp, m, p);
}
virtual tactic * translate(ast_manager & m) {
return alloc(add_bounds_tactic, m, m_params);
}
virtual ~add_bounds_tactic() {
dealloc(m_imp);
}
virtual void updt_params(params_ref const & p) {
m_params = p;
m_imp->updt_params(p);
}
virtual void collect_param_descrs(param_descrs & r) {
r.insert(":add-bound-lower", CPK_NUMERAL, "(default: -2) lower bound to be added to unbounded variables.");
r.insert(":add-bound-upper", CPK_NUMERAL, "(default: 2) upper bound to be added to unbounded variables.");
}
virtual void operator()(goal_ref const & g,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
(*m_imp)(g, result, mc, pc, core);
}
virtual void cleanup() {
ast_manager & m = m_imp->m;
imp * d = m_imp;
#pragma omp critical (tactic_cancel)
{
d = m_imp;
}
dealloc(d);
d = alloc(imp, m, m_params);
#pragma omp critical (tactic_cancel)
{
m_imp = d;
}
}
protected:
virtual void set_cancel(bool f) {
if (m_imp)
m_imp->set_cancel(f);
}
};
tactic * mk_add_bounds_tactic(ast_manager & m, params_ref const & p) {
return clean(alloc(add_bounds_tactic, m, p));
}

View file

@ -0,0 +1,34 @@
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
add_bounds.h
Abstract:
Tactic for bounding unbounded variables.
Author:
Leonardo de Moura (leonardo) 2011-06-30.
Revision History:
--*/
#ifndef _ADD_BOUNDS_H_
#define _ADD_BOUNDS_H_
#include"params.h"
class ast_manager;
class goal;
class tactic;
class probe;
bool is_unbounded(goal const & g);
probe * mk_is_unbounded_probe();
tactic * mk_add_bounds_tactic(ast_manager & m, params_ref const & p = params_ref());
#endif

View file

@ -0,0 +1,240 @@
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
bound_manager.cpp
Abstract:
Collect bounds.
Author:
Leonardo (leonardo) 2011-05-16
Notes:
--*/
#include"bound_manager.h"
#include"ast_smt2_pp.h"
#include"goal.h"
bound_manager::bound_manager(ast_manager & m):
m_util(m) {
}
bound_manager::~bound_manager() {
reset();
}
static decl_kind swap_decl(decl_kind k) {
switch (k) {
case OP_LE: return OP_GE;
case OP_LT: return OP_GT;
case OP_GE: return OP_LE;
case OP_GT: return OP_LT;
default:
UNREACHABLE();
return k;
}
}
decl_kind bound_manager::neg(decl_kind k) {
switch (k) {
case OP_LE: return OP_GT;
case OP_LT: return OP_GE;
case OP_GE: return OP_LT;
case OP_GT: return OP_LE;
default:
UNREACHABLE();
return k;
}
}
void bound_manager::norm(numeral & n, decl_kind & k) {
switch (k) {
case OP_LE: return;
case OP_GE: return;
case OP_LT:
// x < n --> x <= n-1
n--;
k = OP_LE;
return;
case OP_GT:
// x > n --> x >= n+1
n++;
k = OP_GE;
return;
default:
return;
}
}
static bool is_lower(decl_kind k) {
return k == OP_GT || k == OP_GE;
}
static bool is_strict(decl_kind k) {
return k == OP_LT || k == OP_GT;
}
void bound_manager::operator()(expr * f, expr_dependency * d) {
TRACE("bound_manager", tout << "processing:\n" << mk_ismt2_pp(f, m()) << "\n";);
expr * v;
numeral n;
if (is_disjunctive_bound(f, d))
return;
bool pos = true;
while (m().is_not(f, f))
pos = !pos;
if (!is_app(f))
return;
app * t = to_app(f);
if (t->get_family_id() != m_util.get_family_id())
return;
decl_kind k = t->get_decl_kind();
if (k != OP_LE && k != OP_GE && k != OP_LT && k != OP_GT)
return;
expr * lhs = t->get_arg(0);
expr * rhs = t->get_arg(1);
bool is_int;
if (is_uninterp_const(lhs) && m_util.is_numeral(rhs, n, is_int)) {
v = lhs;
}
else if (is_uninterp_const(rhs) && m_util.is_numeral(lhs, n, is_int)) {
v = rhs;
k = swap_decl(k);
}
else {
return;
}
if (!pos)
k = neg(k);
if (is_int)
norm(n, k);
TRACE("bound_manager", tout << "found bound for:\n" << mk_ismt2_pp(v, m()) << "\n";);
bool strict = is_strict(k);
if (is_lower(k)) {
insert_lower(v, strict, n, d);
}
else {
insert_upper(v, strict, n, d);
}
}
void bound_manager::insert_upper(expr * v, bool strict, numeral const & n, expr_dependency * d) {
limit old;
if (m_uppers.find(v, old)) {
if (n < old.first || (n == old.first && strict && !old.second)) {
// improved bound
m_uppers.insert(v, limit(n, strict));
if (d)
m_upper_deps.insert(v, d);
}
}
else {
m_uppers.insert(v, limit(n, strict));
if (d)
m_upper_deps.insert(v, d);
if (!m_lowers.contains(v)) {
m_bounded_vars.push_back(v);
m().inc_ref(v);
}
}
}
void bound_manager::insert_lower(expr * v, bool strict, numeral const & n, expr_dependency * d) {
limit old;
if (m_lowers.find(v, old)) {
if (n > old.first || (n == old.first && strict && !old.second)) {
// improved bound
m_lowers.insert(v, limit(n, strict));
if (d)
m_lower_deps.insert(v, d);
}
}
else {
m_lowers.insert(v, limit(n, strict));
if (d)
m_lower_deps.insert(v, d);
if (!m_uppers.contains(v)) {
m_bounded_vars.push_back(v);
m().inc_ref(v);
}
}
}
bool bound_manager::is_disjunctive_bound(expr * f, expr_dependency * d) {
numeral lo, hi, n;
if (!m().is_or(f)) return false;
unsigned sz = to_app(f)->get_num_args();
if (sz == 0) return false;
expr * x, * y, * v = 0;
bool is_int;
for (unsigned i = 0; i < sz; ++i) {
expr * e = to_app(f)->get_arg(i);
if (!m().is_eq(e, x, y)) return false;
if (is_uninterp_const(x) &&
m_util.is_numeral(y, n, is_int) && is_int &&
(x == v || v == 0)) {
if (v == 0) { v = x; lo = hi = n; }
if (n < lo) lo = n;
if (n > hi) hi = n;
}
else if (is_uninterp_const(y) &&
m_util.is_numeral(x, n, is_int) && is_int &&
(y == v || v == 0)) {
if (v == 0) { v = y; lo = hi = n; }
if (n < lo) lo = n;
if (n > hi) hi = n;
}
else {
return false;
}
}
TRACE("bound_manager", tout << "bounds: " << lo << " " << hi << "\n";);
insert_lower(v, false, lo, d);
insert_upper(v, false, hi, d);
return true;
}
void bound_manager::operator()(assertion_set const & s) {
unsigned sz = s.size();
for (unsigned i = 0; i < sz; i++) {
operator()(s.form(i), 0);
}
}
void bound_manager::operator()(goal const & g) {
unsigned sz = g.size();
for (unsigned i = 0; i < sz; i++) {
operator()(g.form(i), g.dep(i));
}
}
void bound_manager::reset() {
m().dec_array_ref(m_bounded_vars.size(), m_bounded_vars.c_ptr());
m_bounded_vars.finalize();
m_lowers.finalize();
m_uppers.finalize();
m_lower_deps.finalize();
m_upper_deps.finalize();
}
void bound_manager::display(std::ostream & out) const {
numeral n; bool strict;
for (iterator it = begin(); it != end(); ++it) {
expr * v = *it;
if (has_lower(v, n, strict))
out << n << " " << (strict ? "<" : "<=");
else
out << "-oo <";
out << " " << mk_ismt2_pp(v, m()) << " ";
if (has_upper(v, n, strict))
out << (strict ? "<" : "<=") << " " << n;
else
out << "< oo";
out << "\n";
}
}

View file

@ -0,0 +1,111 @@
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
bound_manager.h
Abstract:
Collect bounds.
Author:
Leonardo (leonardo) 2011-05-16
Notes:
--*/
#ifndef _BOUND_MANAGER_H_
#define _BOUND_MANAGER_H_
#include"ast.h"
#include"assertion_set.h"
#include"arith_decl_plugin.h"
class goal;
class bound_manager {
public:
typedef rational numeral;
private:
typedef std::pair<numeral, bool> limit;
arith_util m_util;
obj_map<expr, limit> m_lowers;
obj_map<expr, limit> m_uppers;
obj_map<expr, expr_dependency*> m_lower_deps;
obj_map<expr, expr_dependency*> m_upper_deps;
ptr_vector<expr> m_bounded_vars;
bool is_disjunctive_bound(expr * f, expr_dependency * d);
void insert_lower(expr * v, bool strict, numeral const & n, expr_dependency * d);
void insert_upper(expr * v, bool strict, numeral const & n, expr_dependency * d);
public:
static decl_kind neg(decl_kind k);
static void norm(numeral & n, decl_kind & k);
bound_manager(ast_manager & m);
~bound_manager();
ast_manager & m() const { return m_util.get_manager(); }
void operator()(assertion_set const & s); // TODO: delete
void operator()(goal const & g);
void operator()(expr * n, expr_dependency * d = 0);
bool has_lower(expr * c, numeral & v, bool & strict) const {
limit l;
if (m_lowers.find(c, l)) {
v = l.first;
strict = l.second;
return true;
}
return false;
}
bool has_upper(expr * c, numeral & v, bool & strict) const {
limit l;
if (m_uppers.find(c, l)) {
v = l.first;
strict = l.second;
return true;
}
return false;
}
expr_dependency * lower_dep(expr * c) const {
expr_dependency * d;
if (m_lower_deps.find(c, d))
return d;
return 0;
}
expr_dependency * upper_dep(expr * c) const {
expr_dependency * d;
if (m_upper_deps.find(c, d))
return d;
return 0;
}
bool has_lower(expr * c) const {
return m_lowers.contains(c);
}
bool has_upper(expr * c) const {
return m_uppers.contains(c);
}
typedef ptr_vector<expr>::const_iterator iterator;
/**
\brief Iterator for all bounded constants.
*/
iterator begin() const { return m_bounded_vars.begin(); }
iterator end() const { return m_bounded_vars.end(); }
void reset();
// for debugging purposes
void display(std::ostream & out) const;
};
#endif

View file

@ -0,0 +1,956 @@
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
bound_propagator.cpp
Abstract:
Bound propagators for arithmetic.
Support class for implementing strategies and search procedures
Author:
Leonardo de Moura (leonardo) 2011-06-18.
Revision History:
--*/
#include"bound_propagator.h"
#include<cmath>
// -------------------------------
// Bound Relaxation configuration
//
// The idea is to minimize errors in floating point computations
//
// If RELAX_BOUNDS is undefined, then bound relaxation is disabled.
// Otherwise, lower bounds l are relaxed using the formula
// PRECISION * floor(l * INV_PRECISION + TOLERANCE)
// and upper bounds u as:
// PRECISION * ceil(u * INV_PRECISION - TOLERANCE)
// In the LP literature, the suggested values are
// l := 10^-5 * floor(l*10^5 + 10^-6)
// u := 10^-5 * ceil(u*10^5 - 10^-6)
// I'm using the following values because of strict bounds
// l := 10^-6 * floor(l*10^6 + 10^-7)
// u := 10^-6 * ceil(u*10^6 - 10^-7)
#define RELAX_BOUNDS
#define TOLERANCE 0.0000001
#define PRECISION 0.000001
#define INV_PRECISION 1000000.0
// -------------------------------
bound_propagator::bound::bound(numeral_manager & m,
mpq const & k,
double approx_k,
bool lower,
bool strict,
unsigned lvl,
unsigned ts,
bkind bk,
unsigned c_idx,
assumption a,
bound * prev):
m_approx_k(approx_k),
m_lower(lower),
m_strict(strict),
m_kind(bk),
m_level(lvl),
m_timestamp(ts),
m_prev(prev) {
m.set(m_k, k);
if (bk == DERIVED)
m_constraint_idx = c_idx;
else
m_assumption = a;
}
bound_propagator::bound_propagator(numeral_manager & _m, allocator & a, params_ref const & p):
m(_m),
m_allocator(a),
m_eq_manager(m, a) {
m_timestamp = 0;
m_qhead = 0;
m_conflict = null_var;
updt_params(p);
reset_statistics();
}
bound_propagator::~bound_propagator() {
m.del(m_tmp);
reset();
}
void bound_propagator::del_constraints_core() {
constraint_vector::iterator it = m_constraints.begin();
constraint_vector::iterator end = m_constraints.end();
for (; it != end; ++it) {
del_constraint(*it);
}
m_constraints.reset();
}
void bound_propagator::del_constraints() {
SASSERT(scope_lvl() == 0);
if (m_constraints.empty())
return;
del_constraints_core();
m_constraints.finalize();
vector<wlist>::iterator it = m_watches.begin();
vector<wlist>::iterator end = m_watches.end();
for (; it != end; ++it)
it->finalize();
}
void bound_propagator::del_constraint(constraint & c) {
switch (c.m_kind) {
case LINEAR:
m_eq_manager.del(c.m_eq);
break;
default:
UNREACHABLE();
break;
}
}
void bound_propagator::updt_params(params_ref const & p) {
m_max_refinements = p.get_uint(":bound-max-refinements", 16);
m_threshold = p.get_double(":bound-threshold", 0.05);
m_small_interval = p.get_double(":bound-small-interval", 128);
m_strict2double = p.get_double(":strict2double", 0.00001);
}
void bound_propagator::get_param_descrs(param_descrs & r) {
r.insert(":bound-max-refinements", CPK_UINT, "(default: 16) maximum number of bound refinements (per round) for unbounded variables.");
r.insert(":bound-threshold", CPK_DOUBLE, "(default: 0.05) bound propagation improvement threshold ratio.");
}
void bound_propagator::collect_statistics(statistics & st) const {
st.update("bound conflicts", m_conflicts);
st.update("bound propagations", m_propagations);
st.update("bound false alarms", m_false_alarms);
}
void bound_propagator::reset_statistics() {
m_conflicts = 0;
m_propagations = 0;
m_false_alarms = 0;
}
void bound_propagator::mk_var(var x, bool is_int) {
m_is_int.reserve(x+1, false);
m_dead.reserve(x+1, true);
m_lowers.reserve(x+1, 0);
m_uppers.reserve(x+1, 0);
m_lower_refinements.reserve(x+1, 0);
m_upper_refinements.reserve(x+1, 0);
m_watches.reserve(x+1);
SASSERT(m_dead[x]);
m_is_int[x] = is_int;
m_dead[x] = false;
m_lowers[x] = 0;
m_uppers[x] = 0;
m_lower_refinements[x] = 0;
m_upper_refinements[x] = 0;
m_watches[x].reset();
}
void bound_propagator::del_var(var x) {
SASSERT(!m_dead[x]);
m_dead[x] = true;
// mark constraints containing x as dead.
wlist & wl = m_watches[x];
wlist::iterator it = wl.begin();
wlist::iterator end = wl.end();
for (; it != end; ++it) {
m_constraints[*it].m_dead = true;
}
}
void bound_propagator::mk_eq(unsigned sz, mpq * as, var * xs) {
linear_equation * eq = m_eq_manager.mk(sz, as, xs);
init_eq(eq);
}
void bound_propagator::mk_eq(unsigned sz, mpz * as, var * xs) {
linear_equation * eq = m_eq_manager.mk(sz, as, xs);
init_eq(eq);
}
void bound_propagator::init_eq(linear_equation * eq) {
if (eq == 0)
return;
unsigned c_idx = m_constraints.size();
m_constraints.push_back(constraint());
constraint & new_c = m_constraints.back();
new_c.m_kind = LINEAR;
new_c.m_dead = false;
new_c.m_timestamp = 0;
new_c.m_act = 0;
new_c.m_counter = 0;
new_c.m_eq = eq;
unsigned sz = eq->size();
for (unsigned i = 0; i < sz; i++) {
m_watches[eq->x(i)].push_back(c_idx);
}
if (propagate(c_idx) && scope_lvl() > 0)
m_reinit_stack.push_back(c_idx);
}
void bound_propagator::push() {
m_scopes.push_back(scope());
scope & s = m_scopes.back();
s.m_trail_limit = m_trail.size();
s.m_qhead_old = m_qhead;
s.m_reinit_stack_limit = m_reinit_stack.size();
s.m_timestamp_old = m_timestamp;
s.m_in_conflict = inconsistent();
}
void bound_propagator::undo_trail(unsigned old_sz) {
SASSERT(old_sz <= m_trail.size());
unsigned i = m_trail.size();
while (i > old_sz) {
--i;
trail_info & info = m_trail.back();
var x = info.x();
bool is_lower = info.is_lower();
m_trail.pop_back();
bound * b;
if (is_lower) {
b = m_lowers[x];
m_lowers[x] = b->m_prev;
}
else {
b = m_uppers[x];
m_uppers[x] = b->m_prev;
}
m.del(b->m_k);
b->~bound();
m_allocator.deallocate(sizeof(bound), b);
}
SASSERT(m_trail.size() == old_sz);
}
void bound_propagator::pop(unsigned num_scopes) {
unsigned lvl = scope_lvl();
SASSERT(num_scopes <= lvl);
unsigned new_lvl = lvl - num_scopes;
scope & s = m_scopes[new_lvl];
undo_trail(s.m_trail_limit);
m_timestamp = s.m_timestamp_old;
m_qhead = s.m_qhead_old;
if (!s.m_in_conflict)
m_conflict = null_var;
unsigned reinit_stack_sz = s.m_reinit_stack_limit;
m_scopes.shrink(new_lvl);
// reinitialize
unsigned i = reinit_stack_sz;
unsigned j = reinit_stack_sz;
unsigned sz = m_reinit_stack.size();
for (; i < sz; i++) {
unsigned c_idx = m_reinit_stack[i];
bool p = propagate(c_idx);
if (new_lvl > 0 && p) {
m_reinit_stack[j] = c_idx;
j++;
}
}
m_reinit_stack.shrink(j);
}
bool bound_propagator::assert_lower_core(var x, mpq & k, bool strict, bkind bk, unsigned c_idx, assumption a) {
if (is_int(x)) {
if (m.is_int(k)) {
if (strict)
m.inc(k);
}
else {
m.ceil(k, k);
}
SASSERT(m.is_int(k));
strict = false;
}
TRACE("bound_propagator_detail", tout << "new lower x" << x << " " << m.to_string(k) << " strict: " << strict << "\n";);
bound * old_lower = m_lowers[x];
if (old_lower) {
bool improves = m.gt(k, old_lower->m_k) || (!old_lower->m_strict && strict && m.eq(k, old_lower->m_k));
if (!improves) {
if (bk == DERIVED) {
TRACE("bound_propagator_detail", tout << "false alarm\n";);
m_false_alarms++;
}
return false;
}
}
if (bk == DERIVED) {
TRACE("bound_propagator_derived", tout << "new lower x" << x << " " << m.to_string(k) << " strict: " << strict << "\n";);
m_propagations++;
}
if (scope_lvl() == 0 && bk == DERIVED)
bk = AXIOM; // don't need justification at level 0
double approx_k = m.get_double(k);
TRACE("new_bound", tout << "x" << x << " lower: " << m.to_string(k) << " approx: " << approx_k << "\n";);
#ifdef RELAX_BOUNDS
approx_k = PRECISION*floor(approx_k*INV_PRECISION + TOLERANCE);
TRACE("new_bound", tout << "x" << x << " lower: " << m.to_string(k) << " relaxed approx: " << approx_k << "\n";);
#endif
void * mem = m_allocator.allocate(sizeof(bound));
bound * new_lower = new (mem) bound(m, k, approx_k, true, strict, scope_lvl(), m_timestamp, bk, c_idx, a, old_lower);
m_timestamp++;
m_lowers[x] = new_lower;
m_trail.push_back(trail_info(x, true));
m_lower_refinements[x]++;
check_feasibility(x);
return true;
}
bool bound_propagator::assert_upper_core(var x, mpq & k, bool strict, bkind bk, unsigned c_idx, assumption a) {
if (is_int(x)) {
if (m.is_int(k)) {
if (strict)
m.dec(k);
}
else {
m.floor(k, k);
}
SASSERT(m.is_int(k));
strict = false;
}
TRACE("bound_propagator_detail", tout << "new upper x" << x << " " << m.to_string(k) << " strict: " << strict << "\n";);
bound * old_upper = m_uppers[x];
if (old_upper) {
bool improves = m.lt(k, old_upper->m_k) || (!old_upper->m_strict && strict && m.eq(k, old_upper->m_k));
if (!improves) {
if (bk == DERIVED) {
TRACE("bound_propagator_detail", tout << "false alarm\n";);
m_false_alarms++;
}
return false;
}
}
if (bk == DERIVED) {
m_propagations++;
TRACE("bound_propagator_derived", tout << "new upper x" << x << " " << m.to_string(k) << " strict: " << strict << "\n";);
}
if (scope_lvl() == 0 && bk == DERIVED)
bk = AXIOM; // don't need justification at level 0
double approx_k = m.get_double(k);
TRACE("new_bound", tout << "x" << x << " upper: " << m.to_string(k) << " approx: " << approx_k << "\n";);
#ifdef RELAX_BOUNDS
approx_k = PRECISION*ceil(approx_k*INV_PRECISION - TOLERANCE);
TRACE("new_bound", tout << "x" << x << " upper: " << m.to_string(k) << " relaxed approx: " << approx_k << "\n";);
#endif
void * mem = m_allocator.allocate(sizeof(bound));
bound * new_upper = new (mem) bound(m, k, approx_k, false, strict, scope_lvl(), m_timestamp, bk, c_idx, a, m_uppers[x]);
m_timestamp++;
m_uppers[x] = new_upper;
m_trail.push_back(trail_info(x, false));
m_upper_refinements[x]++;
check_feasibility(x);
return true;
}
bool bound_propagator::get_interval_size(var x, double & r) const {
bound * l = m_lowers[x];
bound * u = m_uppers[x];
if (l && u) {
r = u->m_approx_k - l->m_approx_k;
return true;
}
return false;
}
template<bool LOWER>
bool bound_propagator::relevant_bound(var x, double new_k) const {
TRACE("bound_propagator_detail", tout << "relevant_bound x" << x << " " << new_k << " LOWER: " << LOWER << "\n";
if (LOWER && has_lower(x)) tout << "old: " << m.to_string(m_lowers[x]->m_k) << " | " << m_lowers[x]->m_approx_k << "\n";
if (!LOWER && has_upper(x)) tout << "old: " << m.to_string(m_uppers[x]->m_k) << " | " << m_uppers[x]->m_approx_k << "\n";);
bound * b = LOWER ? m_lowers[x] : m_uppers[x];
if (b == 0)
return true; // variable did not have a bound
double interval_size;
bool bounded = get_interval_size(x, interval_size);
if (!is_int(x)) {
// check if the improvement is significant
double improvement;
double abs_k = b->m_approx_k;
if (abs_k < 0.0)
abs_k -= abs_k;
if (bounded)
improvement = m_threshold * std::max(std::min(interval_size, abs_k), 1.0);
else
improvement = m_threshold * std::max(abs_k, 1.0);
if (LOWER) {
if (new_k <= b->m_approx_k + improvement) {
TRACE("bound_propagator", tout << "LOWER new: " << new_k << " old: " << b->m_approx_k << " improvement is too small\n";);
return false; // improvement is too small
}
}
else {
if (new_k >= b->m_approx_k - improvement) {
TRACE("bound_propagator", tout << "UPPER new: " << new_k << " old: " << b->m_approx_k << " improvement is too small\n";);
return false; // improvement is too small
}
}
}
else {
if (LOWER) {
if (new_k < b->m_approx_k + 1.0)
return false; // no improvement
}
else {
if (new_k > b->m_approx_k - 1.0)
return false; // no improvement
}
}
if (bounded && interval_size <= m_small_interval)
return true;
if (LOWER)
return m_lower_refinements[x] < m_max_refinements;
else
return m_upper_refinements[x] < m_max_refinements;
}
bool bound_propagator::relevant_lower(var x, double approx_k) const {
return relevant_bound<true>(x, approx_k);
}
bool bound_propagator::relevant_upper(var x, double approx_k) const {
return relevant_bound<false>(x, approx_k);
}
void bound_propagator::check_feasibility(var x) {
if (inconsistent())
return;
bound * l = m_lowers[x];
bound * u = m_uppers[x];
if (l && u) {
if (m.lt(l->m_k, u->m_k))
return;
if (!l->m_strict && !u->m_strict && m.eq(l->m_k, u->m_k))
return;
m_conflict = x;
m_conflicts++;
SASSERT(inconsistent());
TRACE("bound_propagator", tout << "inconsistency detected: x" << x << "\n"; display(tout););
}
}
void bound_propagator::propagate() {
m_to_reset_ts.reset();
while (m_qhead < m_trail.size()) {
if (inconsistent())
break;
trail_info & info = m_trail[m_qhead];
var x = info.x();
bool is_lower = info.is_lower();
bound * b = is_lower ? m_lowers[x] : m_uppers[x];
SASSERT(b);
unsigned ts = b->m_timestamp;
TRACE("bound_propagator_detail", tout << "propagating x" << x << "\n";);
m_qhead++;
wlist const & wl = m_watches[x];
wlist::const_iterator it = wl.begin();
wlist::const_iterator end = wl.end();
for (; it != end; ++it) {
unsigned c_idx = *it;
constraint & c = m_constraints[c_idx];
// We don't need to visit c if it was already propagated using b.
// Whenever we visit c we store in c.m_timestamp the current timestamp
// So, we know that c was already propagated any bound using bounds with timestamp lower than c.m_timestamp.
if (ts >= c.m_timestamp) {
if (c.m_timestamp == 0)
m_to_reset_ts.push_back(c_idx);
c.m_timestamp = m_timestamp;
propagate(c_idx);
}
}
}
unsigned_vector::iterator it = m_to_reset_ts.begin();
unsigned_vector::iterator end = m_to_reset_ts.end();
for (; it != end; ++it)
m_constraints[*it].m_timestamp = 0;
}
bool bound_propagator::propagate(unsigned c_idx) {
constraint const & c = m_constraints[c_idx];
if (c.m_dead)
return false;
if (c.m_kind == LINEAR)
return propagate_eq(c_idx);
return false;
}
bool bound_propagator::propagate_eq(unsigned c_idx) {
constraint const & c = m_constraints[c_idx];
linear_equation * eq = c.m_eq;
#if 0
{
static unsigned counter = 0;
static unsigned visited = 0;
counter++;
visited += eq->size();
if (counter % 1000 == 0)
verbose_stream() << "[bound-propagator] :propagate-eq " << counter << " :visited-vars " << visited << std::endl;
}
#endif
TRACE("bound_propagator_detail", tout << "propagating using eq: "; m_eq_manager.display(tout, *eq); tout << "\n";);
// ll = (Sum_{a_i < 0} -a_i*lower(x_i)) + (Sum_{a_i > 0} -a_i * upper(x_i))
// uu = (Sum_{a_i > 0} -a_i*lower(x_i)) + (Sum_{a_i < 0} -a_i * upper(x_i))
unsigned ll_i = UINT_MAX; // position of the variable that couldn't contribute to ll
unsigned uu_i = UINT_MAX; // position of the variable that coundn't contribute to uu
bool ll_failed = false;
bool uu_failed = false;
double ll = 0.0;
double uu = 0.0;
unsigned sz = eq->size();
for (unsigned i = 0; i < sz; i++) {
var x_i = eq->x(i);
double a_i = eq->approx_a(i);
bound * l_i = m_lowers[x_i];
bound * u_i = m_uppers[x_i];
if (a_i < 0.0) {
if (!ll_failed) {
if (l_i == 0) {
if (ll_i == UINT_MAX)
ll_i = i;
else
ll_failed = true;
}
else {
ll -= a_i * l_i->m_approx_k;
}
}
if (!uu_failed) {
if (u_i == 0) {
if (uu_i == UINT_MAX)
uu_i = i;
else
uu_failed = true;
}
else {
uu -= a_i * u_i->m_approx_k;
}
}
}
else {
if (!ll_failed) {
if (u_i == 0) {
if (ll_i == UINT_MAX)
ll_i = i;
else
ll_failed = true;
}
else {
ll -= a_i * u_i->m_approx_k;
}
}
if (!uu_failed) {
if (l_i == 0) {
if (uu_i == UINT_MAX)
uu_i = i;
else
uu_failed = true;
}
else {
uu -= a_i * l_i->m_approx_k;
}
}
}
if (ll_failed && uu_failed)
return false; // nothing to propagate
}
bool propagated = false;
SASSERT(!ll_failed || !uu_failed);
if (ll_i == UINT_MAX || uu_i == UINT_MAX) {
for (unsigned i = 0; i < sz; i++) {
var x_i = eq->x(i);
double a_i = eq->approx_a(i);
bound * l_i = m_lowers[x_i];
bound * u_i = m_uppers[x_i];
// ll = (Sum_{a_i < 0} -a_i*lower(x_i)) + (Sum_{a_i > 0} -a_i * upper(x_i))
// uu = (Sum_{a_i > 0} -a_i*lower(x_i)) + (Sum_{a_i < 0} -a_i * upper(x_i))
if (ll_i == UINT_MAX) {
// can propagate a lower bound for a_i*x_i
if (a_i > 0.0) {
// can propagate a lower bound for x_i
double new_k = (ll + a_i * u_i->m_approx_k)/a_i;
if (relevant_lower(x_i, new_k) && propagate_lower(c_idx, i))
propagated = true;
}
else {
// a_i < 0.0
// can propagate a upper bound for x_i
double new_k = (ll + a_i * l_i->m_approx_k)/a_i;
if (relevant_upper(x_i, new_k) && propagate_upper(c_idx, i))
propagated = true;
}
}
if (uu_i == UINT_MAX) {
// can propagate an upper bound for a_i*x_i
if (a_i > 0.0) {
// can propagate a upper bound for x_i
double new_k = (uu + a_i * l_i->m_approx_k)/a_i;
if (relevant_upper(x_i, new_k) && propagate_upper(c_idx, i))
propagated = true;
}
else {
// a_i < 0.0
// can propagate a lower bound for x_i
double new_k = (uu + a_i * u_i->m_approx_k)/a_i;
if (relevant_lower(x_i, new_k) && propagate_lower(c_idx, i))
propagated = true;
}
}
}
}
if (!ll_failed && ll_i != UINT_MAX) {
// can propagate a lower bound for the monomial at position ll_i
var x_i = eq->x(ll_i);
double a_i = eq->approx_a(ll_i);
double new_k = ll/a_i;
if (a_i > 0.0) {
if (relevant_lower(x_i, new_k) && propagate_lower(c_idx, ll_i))
propagated = true;
}
else {
if (relevant_upper(x_i, new_k) && propagate_upper(c_idx, ll_i))
propagated = true;
}
}
if (!uu_failed && uu_i != UINT_MAX) {
// can propagate a upper bound for the monomial at position uu_i
var x_i = eq->x(uu_i);
double a_i = eq->approx_a(uu_i);
double new_k = uu/a_i;
if (a_i > 0.0) {
if (relevant_upper(x_i, new_k) && propagate_upper(c_idx, uu_i))
propagated = true;
}
else {
if (relevant_lower(x_i, new_k) && propagate_lower(c_idx, uu_i))
propagated = true;
}
}
return propagated;
}
/**
\brief Try to propagate a lower bound for the variable stored at position i, using mpq's (rationals).
When this method is invoked, we know that all other variables have the "right" bounds, and
using doubles we improve the current known bound.
*/
bool bound_propagator::propagate_lower(unsigned c_idx, unsigned i) {
constraint const & c = m_constraints[c_idx];
linear_equation * eq = c.m_eq;
var x_i = eq->x(i);
mpz const & a_i = eq->a(i);
unsigned sz = eq->size();
mpq k;
bool strict = false;
bool neg_a_i = m.is_neg(a_i);
for (unsigned j = 0; j < sz; j++) {
if (i == j)
continue;
var x_j = eq->x(j);
mpz const & a_j = eq->a(j);
bound * b_j = (m.is_neg(a_j) == neg_a_i) ? m_uppers[x_j] : m_lowers[x_j];
TRACE("bound_propagator_step_detail", tout << "k: " << m.to_string(k) << " b_j->m_k: " << m.to_string(b_j->m_k) <<
" a_j: " << m.to_string(a_j) << "\n";);
SASSERT(b_j);
if (b_j->m_strict)
strict = true;
m.addmul(k, a_j, b_j->m_k, k);
}
TRACE("bound_propagator_step_detail", tout << "k: " << m.to_string(k) << "\n";);
m.neg(k);
m.div(k, a_i, k);
TRACE("bound_propagator_step", tout << "propagating lower x" << x_i << " " << m.to_string(k) << " strict: " << strict << " using\n";
m_eq_manager.display(tout, *eq); tout << "\n"; display_bounds_of(tout, *eq););
bool r = assert_lower_core(x_i, k, strict, DERIVED, c_idx, null_assumption);
m.del(k);
return r;
}
/**
\brief Try to propagate a upper bound for the variable stored at position i, using mpq's (rationals).
When this method is invoked, we know that all other variables have the "right" bounds, and
using doubles we improve the current known bound.
*/
bool bound_propagator::propagate_upper(unsigned c_idx, unsigned i) {
constraint const & c = m_constraints[c_idx];
linear_equation * eq = c.m_eq;
var x_i = eq->x(i);
mpz const & a_i = eq->a(i);
unsigned sz = eq->size();
mpq k;
bool strict = false;
bool neg_a_i = m.is_neg(a_i);
for (unsigned j = 0; j < sz; j++) {
if (i == j)
continue;
var x_j = eq->x(j);
mpz const & a_j = eq->a(j);
bound * b_j = (m.is_neg(a_j) == neg_a_i) ? m_lowers[x_j] : m_uppers[x_j];
SASSERT(b_j);
if (b_j->m_strict)
strict = true;
m.addmul(k, a_j, b_j->m_k, k);
}
m.neg(k);
m.div(k, a_i, k);
TRACE("bound_propagator_step", tout << "propagating upper x" << x_i << " " << m.to_string(k) << " strict: " << strict << " using\n";
m_eq_manager.display(tout, *eq); tout << "\n"; display_bounds_of(tout, *eq););
bool r = assert_upper_core(x_i, k, strict, DERIVED, c_idx, null_assumption);
m.del(k);
return r;
}
void bound_propagator::reset() {
undo_trail(0);
del_constraints_core();
m_constraints.finalize();
m_is_int.finalize();
m_dead.finalize();
m_lowers.finalize();
m_uppers.finalize();
m_watches.finalize();
m_trail.finalize();
m_qhead = 0;
m_reinit_stack.finalize();
m_lower_refinements.finalize();
m_upper_refinements.finalize();
m_timestamp = 0;
m_conflict = null_var;
m_scopes.finalize();
}
bool bound_propagator::lower(var x, mpq & k, bool & strict, unsigned & ts) const {
bound * b = m_lowers[x];
if (!b)
return false;
m.set(k, b->m_k);
strict = b->m_strict;
ts = b->m_timestamp;
return true;
}
bool bound_propagator::upper(var x, mpq & k, bool & strict, unsigned & ts) const {
bound * b = m_uppers[x];
if (!b)
return false;
m.set(k, b->m_k);
strict = b->m_strict;
ts = b->m_timestamp;
return true;
}
bound_propagator::bound * bound_propagator::bound::at(unsigned timestamp) {
bound * r = this;
while (r != 0 && r->m_timestamp >= timestamp)
r = r->m_prev;
return r;
}
/**
\brief Return true if the coefficient of x in eq is positive
*/
bool bound_propagator::is_a_i_pos(linear_equation const & eq, var x) const {
unsigned i = eq.pos(x);
if (i == UINT_MAX)
return false;
return m.is_pos(eq.a(i));
}
void bound_propagator::explain(var x, bound * b, unsigned ts, assumption_vector & ex) const {
if (!b)
return;
b = b->at(ts);
if (!b)
return;
if (b->m_kind == AXIOM || b->m_kind == DECISION)
return;
if (b->m_kind == ASSUMPTION) {
ex.push_back(b->m_assumption);
return;
}
svector<var_bound> & todo = const_cast<bound_propagator*>(this)->m_todo;
todo.reset();
unsigned qhead = 0;
todo.push_back(var_bound(x, b));
b->m_mark = true;
while (qhead < todo.size()) {
var_bound & vb = todo[qhead];
qhead ++;
var x = vb.first;
bound * b = vb.second;
SASSERT(b->kind() == ASSUMPTION || b->kind() == DERIVED);
if (b->kind() == ASSUMPTION) {
ex.push_back(b->m_assumption);
continue;
}
SASSERT(b->kind() == DERIVED);
constraint const & c = m_constraints[b->m_constraint_idx];
switch (c.m_kind) {
case LINEAR: {
linear_equation * eq = c.m_eq;
bool is_lower = b->is_lower();
if (!is_a_i_pos(*eq, x))
is_lower = !is_lower;
unsigned sz = eq->size();
for (unsigned i = 0; i < sz; i++) {
var x_i = eq->x(i);
if (x_i == x)
continue;
bound * b = (m.is_neg(eq->a(i)) == is_lower) ? m_lowers[x_i] : m_uppers[x_i];
SASSERT(b);
if (b->kind() == DERIVED || b->kind() == ASSUMPTION) {
if (!b->m_mark) {
b->m_mark = true;
todo.push_back(var_bound(x_i, b));
}
}
}
break;
}
default:
break;
}
}
unsigned sz = todo.size();
for (unsigned i = 0; i < sz; i++)
todo[i].second->m_mark = false;
todo.reset();
}
/**
\brief Compute lower (upper) bound for the linear polynomial as[0]*xs[0] + ... + as[sz-1]*xs[sz-1]
Return false if the lower (upper) bound is -oo (oo)
*/
template<bool LOWER, typename Numeral>
bool bound_propagator::get_bound(unsigned sz, Numeral const * as, var const * xs, mpq & r, bool & st) const {
st = false;
m.reset(r);
for (unsigned i = 0; i < sz; i++) {
var x_i = xs[i];
Numeral const & a_i = as[i];
if (m.is_zero(a_i))
continue;
bound * b = (m.is_neg(a_i) == LOWER) ? m_uppers[x_i] : m_lowers[x_i];
if (!b) {
m.reset(r);
return false;
}
if (b->m_strict)
st = true;
m.addmul(r, a_i, b->m_k, r);
}
return true;
}
bool bound_propagator::lower(unsigned sz, mpq const * as, var const * xs, mpq & r, bool & st) const {
return get_bound<true, mpq>(sz, as, xs, r, st);
}
bool bound_propagator::upper(unsigned sz, mpq const * as, var const * xs, mpq & r, bool & st) const {
return get_bound<false, mpq>(sz, as, xs, r, st);
}
void bound_propagator::display_bounds_of(std::ostream & out, linear_equation const & eq) const {
for (unsigned i = 0; i < eq.size(); i++) {
display_var_bounds(out, eq.x(i));
out << "\n";
}
}
void bound_propagator::display_var_bounds(std::ostream & out, var x, bool approx, bool precise) const {
if (m_lowers[x]) {
if (precise)
out << m.to_string(m_lowers[x]->m_k);
if (precise && approx)
out << " | ";
if (approx)
out << m_lowers[x]->m_approx_k;
out << " " << (m_lowers[x]->m_strict ? "<" : "<=");
}
else {
out << "-oo <";
}
out << " x" << x << " ";
if (m_uppers[x]) {
out << (m_uppers[x]->m_strict ? "<" : "<=") << " ";
if (precise)
out << m.to_string(m_uppers[x]->m_k);
if (precise && approx)
out << " | ";
if (approx)
out << m_uppers[x]->m_approx_k;
}
else {
out << "< oo";
}
}
void bound_propagator::display_bounds(std::ostream & out, bool approx, bool precise) const {
unsigned num_vars = m_dead.size();
for (unsigned x = 0; x < num_vars; x++) {
if (!is_dead(x)) {
display_var_bounds(out, x, approx, precise);
out << "\n";
}
}
}
void bound_propagator::display_constraints(std::ostream & out) const {
constraint_vector::const_iterator it = m_constraints.begin();
constraint_vector::const_iterator end = m_constraints.end();
for (; it != end; ++it) {
constraint const & c = *it;
if (c.m_kind == LINEAR) {
m_eq_manager.display(out, *(c.m_eq));
out << "\n";
}
}
}
void bound_propagator::display(std::ostream & out) const {
display_bounds(out);
display_constraints(out);
}

View file

@ -0,0 +1,265 @@
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
bound_propagator.h
Abstract:
Bound propagators for arithmetic.
Support class for implementing strategies and search procedures
Author:
Leonardo de Moura (leonardo) 2011-06-18.
Revision History:
--*/
#ifndef _BOUND_PROPAGATOR_H_
#define _BOUND_PROPAGATOR_H_
#include"mpq.h"
#include"vector.h"
#include"params.h"
#include"statistics.h"
#include"numeral_buffer.h"
#include"linear_equation.h"
class bound_propagator {
public:
typedef unsigned var;
typedef unsigned assumption;
typedef unsynch_mpq_manager numeral_manager;
typedef unsigned_vector assumption_vector;
typedef unsigned constraint_id;
typedef numeral_buffer<mpz, numeral_manager> mpz_buffer;
typedef svector<double> double_vector;
static const assumption null_assumption = UINT_MAX;
static const var null_var = UINT_MAX;
static const unsigned null_constraint_idx = UINT_MAX;
class trail_info {
unsigned m_x_lower;
public:
trail_info(var x, bool is_lower):m_x_lower((x << 1) + static_cast<unsigned>(is_lower)) {}
trail_info():m_x_lower(UINT_MAX) {}
var x() const { return m_x_lower >> 1; }
bool is_lower() const { return (m_x_lower & 1) != 0; }
};
protected:
enum ckind { LINEAR // only linear equalities so far.
};
/**
\brief Constraints don't need justification.
*/
class constraint {
friend class bound_propagator;
unsigned m_kind:2;
unsigned m_dead:1;
unsigned m_timestamp; // Constraint tried to propagate new bounds using bounds with timestamp < m_timestamp.
unsigned m_act; // activity
unsigned m_counter; // number of times the constraint propagated
union {
linear_equation * m_eq;
};
};
enum bkind { AXIOM, // doesn't need justification
ASSUMPTION, // aka external case-split, it is used to connect with external search engine.
DERIVED, // implied
DECISION // internal case-split
};
struct bound {
mpq m_k;
double m_approx_k;
unsigned m_lower:1;
unsigned m_strict:1;
unsigned m_mark:1;
unsigned m_kind:2;
unsigned m_level:27;
unsigned m_timestamp;
union {
assumption m_assumption;
unsigned m_constraint_idx;
};
bound * m_prev;
bound(numeral_manager & m, mpq const & k, double approx_k, bool lower, bool strict, unsigned lvl, unsigned ts, bkind bk,
unsigned c_idx, assumption a, bound * prev);
bound * at(unsigned timestamp);
bkind kind() const { return static_cast<bkind>(m_kind); }
bool is_lower() const { return m_lower != 0; }
};
typedef ptr_vector<bound> var2bound;
typedef svector<var> var_vector;
typedef svector<constraint> constraint_vector;
typedef unsigned_vector c_idx_vector;
typedef c_idx_vector wlist;
typedef small_object_allocator allocator;
typedef linear_equation_manager lin_eq_manager;
numeral_manager & m;
allocator & m_allocator;
lin_eq_manager m_eq_manager;
constraint_vector m_constraints;
char_vector m_is_int;
char_vector m_dead;
var2bound m_lowers;
var2bound m_uppers;
vector<wlist> m_watches;
svector<trail_info> m_trail;
unsigned m_qhead;
c_idx_vector m_reinit_stack;
unsigned_vector m_lower_refinements; // number of times a lower bound was propagated for each variable (loop prevention)
unsigned_vector m_upper_refinements; // number of times a upper bound was propagated for each variable (loop prevention)
unsigned m_timestamp;
var m_conflict;
mpq m_tmp;
struct scope {
unsigned m_trail_limit;
unsigned m_qhead_old;
unsigned m_reinit_stack_limit;
unsigned m_timestamp_old:31;
unsigned m_in_conflict:1;
};
svector<scope> m_scopes;
unsigned_vector m_to_reset_ts; // temp field: ids of the constraints we must reset the field m_timestamp
// config
unsigned m_max_refinements; // maximum number of refinements per round
double m_small_interval;
double m_threshold; // improvement threshold
double m_strict2double;
// statistics
unsigned m_conflicts;
unsigned m_propagations;
unsigned m_false_alarms;
void del_constraint(constraint & cnstr);
void del_constraints_core();
template<bool LOWER>
bool relevant_bound(var x, double approx_k) const;
bool relevant_lower(var x, double approx_k) const;
bool relevant_upper(var x, double approx_k) const;
bool get_interval_size(var x, double & r) const;
void check_feasibility(var x);
bool assert_lower_core(var x, mpq & k, bool strict, bkind bk, unsigned c_idx, assumption a);
bool assert_upper_core(var x, mpq & k, bool strict, bkind bk, unsigned c_idx, assumption a);
bool propagate(unsigned c_idx);
bool propagate_eq(unsigned c_idx);
bool propagate_lower(unsigned c_idx, unsigned i);
bool propagate_upper(unsigned c_idx, unsigned i);
void undo_trail(unsigned old_sz);
typedef std::pair<var, bound *> var_bound;
svector<var_bound> m_todo;
void explain(var x, bound * b, unsigned ts, assumption_vector & ex) const;
bool is_a_i_pos(linear_equation const & eq, var x) const;
template<bool LOWER, typename Numeral>
bool get_bound(unsigned sz, Numeral const * as, var const * xs, mpq & r, bool & st) const;
void init_eq(linear_equation * eq);
public:
bound_propagator(numeral_manager & m, allocator & a, params_ref const & p);
~bound_propagator();
void updt_params(params_ref const & p);
static void get_param_descrs(param_descrs & r);
void collect_statistics(statistics & st) const;
void reset_statistics();
double strict2double() const { return m_strict2double; }
bool is_int(var x) const { return m_is_int[x] != 0; }
unsigned scope_lvl() const { return m_scopes.size(); }
void mk_var(var x, bool is_int);
void del_var(var x);
bool is_dead(var x) const { return m_dead[x] != 0; }
void mk_eq(unsigned sz, mpq * as, var * xs);
void mk_eq(unsigned sz, mpz * as, var * xs);
void del_constraints();
void assert_lower(var x, mpq const & k, bool strict, assumption a = null_assumption) {
m.set(m_tmp, k);
assert_lower_core(x, m_tmp, strict, a == null_assumption ? AXIOM : ASSUMPTION, 0, a);
}
void assert_upper(var x, mpq const & k, bool strict, assumption a = null_assumption) {
m.set(m_tmp, k);
assert_upper_core(x, m_tmp, strict, a == null_assumption ? AXIOM : ASSUMPTION, 0, a);
}
void assert_decided_lower(var x, mpq const & k) {
m.set(m_tmp, k);
assert_lower_core(x, m_tmp, false, DECISION, 0, null_assumption);
}
void assert_decided_upper(var x, mpq const & k) {
m.set(m_tmp, k);
assert_upper_core(x, m_tmp, false, DECISION, 0, null_assumption);
}
void propagate();
void push();
void pop(unsigned num_scopes);
void reset();
bool has_lower(var x) const { return m_lowers[x] != 0; }
bool has_upper(var x) const { return m_uppers[x] != 0; }
bool lower(var x, mpq & k, bool & strict, unsigned & ts) const;
bool upper(var x, mpq & k, bool & strict, unsigned & ts) const;
bool is_fixed(var x) const { return has_lower(x) && has_upper(x) && m.eq(m_lowers[x]->m_k, m_uppers[x]->m_k) && !inconsistent(); }
mpq const & lower(var x, bool & strict) const { SASSERT(has_lower(x)); bound * b = m_lowers[x]; strict = b->m_strict; return b->m_k; }
mpq const & upper(var x, bool & strict) const { SASSERT(has_upper(x)); bound * b = m_uppers[x]; strict = b->m_strict; return b->m_k; }
mpq const & lower(var x) const { SASSERT(has_lower(x)); return m_lowers[x]->m_k; }
mpq const & upper(var x) const { SASSERT(has_upper(x)); return m_uppers[x]->m_k; }
double approx_lower(var x) const {
SASSERT(has_lower(x));
return m_lowers[x]->m_strict ? m_lowers[x]->m_approx_k + m_strict2double : m_lowers[x]->m_approx_k;
}
double approx_upper(var x) const {
SASSERT(has_upper(x));
return m_uppers[x]->m_strict ? m_uppers[x]->m_approx_k - m_strict2double : m_uppers[x]->m_approx_k;
}
bool is_zero(var x) const { return has_lower(x) && has_upper(x) && m.is_zero(lower(x)) && m.is_zero(upper(x)); }
void explain_lower(var x, unsigned ts, assumption_vector & ex) const { explain(x, m_lowers[x], ts, ex); }
void explain_upper(var x, unsigned ts, assumption_vector & ex) const { explain(x, m_uppers[x], ts, ex); }
void explain_lower(var x, assumption_vector & ex) const { explain_lower(x, m_timestamp, ex); }
void explain_upper(var x, assumption_vector & ex) const { explain_upper(x, m_timestamp, ex); }
var conflict_var() const { return m_conflict; }
bool inconsistent() const { return m_conflict != null_var; }
unsigned trail_size() const { return m_trail.size(); }
unsigned qhead() const { return m_qhead; }
typedef svector<trail_info>::const_iterator trail_iterator;
trail_iterator begin_trail() const { return m_trail.begin(); }
trail_iterator end_trail() const { return m_trail.end(); }
bool lower(unsigned sz, mpq const * as, var const * xs, mpq & r, bool & st) const;
bool upper(unsigned sz, mpq const * as, var const * xs, mpq & r, bool & st) const;
void display(std::ostream & out) const;
void display_var_bounds(std::ostream & out, var x, bool approx = true, bool precise = true) const;
void display_bounds(std::ostream & out, bool approx = true, bool precise = true) const;
void display_precise_bounds(std::ostream & out) const { display_bounds(out, false, true); }
void display_approx_bounds(std::ostream & out) const { display_bounds(out, true, false); }
void display_constraints(std::ostream & out) const;
void display_bounds_of(std::ostream & out, linear_equation const & eq) const;
unsigned get_num_false_alarms() const { return m_false_alarms; }
unsigned get_num_propagations() const { return m_propagations; }
};
#endif

View file

@ -0,0 +1,349 @@
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
degree_shift_tactic.cpp
Abstract:
Simple degree shift procedure.
Basic idea: if goal G contains a real variable x, x occurs with degrees
d_1, ..., d_k in G, and n = gcd(d_1, ..., d_k) > 1.
Then, replace x^n with a new fresh variable y.
Author:
Leonardo de Moura (leonardo) 2011-12-30.
Revision History:
--*/
#include"tactical.h"
#include"filter_model_converter.h"
#include"extension_model_converter.h"
#include"cooperate.h"
#include"arith_decl_plugin.h"
#include"simplify_tactic.h"
#include"ast_smt2_pp.h"
#include"rewriter_def.h"
class degree_shift_tactic : public tactic {
struct imp {
ast_manager & m;
arith_util m_autil;
obj_map<app, rational> m_var2degree;
obj_map<app, app*> m_var2var;
obj_map<app, proof*> m_var2pr;
expr_ref_vector m_pinned;
ptr_vector<expr> m_todo;
rational m_one;
bool m_produce_models;
bool m_produce_proofs;
volatile bool m_cancel;
expr * mk_power(expr * t, rational const & k) {
if (k.is_one())
return t;
else
return m_autil.mk_power(t, m_autil.mk_numeral(k, false));
}
struct rw_cfg : public default_rewriter_cfg {
imp & o;
rw_cfg(imp & _o):o(_o) {}
br_status reduce_app(func_decl * f, unsigned num, expr * const * args, expr_ref & result, proof_ref & result_pr) {
arith_util & u = o.m_autil;
if (!is_decl_of(f, u.get_family_id(), OP_POWER) || !is_app(args[0]))
return BR_FAILED;
ast_manager & m = o.m;
rational g;
app * t = to_app(args[0]);
if (!o.m_var2degree.find(t, g))
return BR_FAILED;
SASSERT(g > rational(1));
SASSERT(g.is_int());
rational k;
VERIFY(u.is_numeral(args[1], k));
SASSERT(gcd(k, g) == g);
rational new_k = div(k, g);
expr * new_arg = o.m_var2var.find(t);
result = o.mk_power(new_arg, new_k);
if (o.m_produce_proofs) {
proof * pr = o.m_var2pr.find(t);
app * fact = m.mk_eq(m.mk_app(f, num, args), result);
result_pr = m.mk_th_lemma(u.get_family_id(), fact, 1, &pr);
}
return BR_DONE;
}
};
class rw : public rewriter_tpl<rw_cfg> {
rw_cfg m_cfg;
public:
rw(imp & o):
rewriter_tpl<rw_cfg>(o.m, o.m_produce_proofs, m_cfg),
m_cfg(o) {
}
};
scoped_ptr<rw> m_rw;
imp(ast_manager & _m):
m(_m),
m_autil(_m),
m_pinned(_m),
m_one(1),
m_rw(0) {
m_cancel = false;
}
void set_cancel(bool f) {
m_cancel = f;
}
void checkpoint() {
if (m_cancel)
throw tactic_exception(TACTIC_CANCELED_MSG);
cooperate("degree_shift");
}
void visit(expr * t, expr_fast_mark1 & visited) {
if (!visited.is_marked(t)) {
visited.mark(t);
m_todo.push_back(t);
}
}
void save_degree(expr * t, rational const & k) {
SASSERT(k.is_int());
if (is_uninterp_const(t) && m_autil.is_real(t)) {
rational old_k;
if (m_var2degree.find(to_app(t), old_k)) {
old_k = gcd(k, old_k);
m_var2degree.insert(to_app(t), old_k);
}
else {
m_var2degree.insert(to_app(t), k);
}
}
}
void visit_args(expr * t, expr_fast_mark1 & visited) {
if (is_app(t)) {
unsigned num_args = to_app(t)->get_num_args();
for (unsigned i = 0; i < num_args; i++) {
expr * arg = to_app(t)->get_arg(i);
save_degree(arg, m_one);
visit(arg, visited);
}
}
}
void collect(expr * t, expr_fast_mark1 & visited) {
rational k;
visit(t, visited);
while (!m_todo.empty()) {
checkpoint();
expr * t = m_todo.back();
m_todo.pop_back();
if (is_var(t))
continue;
if (is_quantifier(t)) {
unsigned num_children = to_quantifier(t)->get_num_children();
for (unsigned i = 0; i < num_children; i ++)
visit(to_quantifier(t)->get_child(i), visited);
}
else {
SASSERT(is_app(t));
if (m_autil.is_power(t) && m_autil.is_numeral(to_app(t)->get_arg(1), k) && k.is_int() && k.is_pos()) {
expr * arg = to_app(t)->get_arg(0);
save_degree(arg, k);
visit_args(arg, visited);
}
else {
visit_args(t, visited);
}
}
}
}
void display_candidates(std::ostream & out) {
out << "candidates:\n";
obj_map<app, rational>::iterator it = m_var2degree.begin();
obj_map<app, rational>::iterator end = m_var2degree.end();
for (; it != end; ++it) {
if (!it->m_value.is_one()) {
out << "POWER: " << it->m_value << "\n" << mk_ismt2_pp(it->m_key, m) << "\n";
}
}
}
void collect(goal const & g) {
m_var2degree.reset();
expr_fast_mark1 visited;
unsigned sz = g.size();
for (unsigned i = 0; i < sz; i++) {
collect(g.form(i), visited);
}
TRACE("degree_shift", display_candidates(tout););
}
void discard_non_candidates() {
m_pinned.reset();
ptr_vector<app> to_delete;
obj_map<app, rational>::iterator it = m_var2degree.begin();
obj_map<app, rational>::iterator end = m_var2degree.end();
for (; it != end; ++it) {
if (it->m_value.is_one())
to_delete.push_back(it->m_key);
else
m_pinned.push_back(it->m_key); // make sure it is not deleted during simplifications
}
ptr_vector<app>::iterator it2 = to_delete.begin();
ptr_vector<app>::iterator end2 = to_delete.end();
for (; it2 != end2; ++it2)
m_var2degree.erase(*it2);
}
void prepare_substitution(model_converter_ref & mc) {
SASSERT(!m_var2degree.empty());
filter_model_converter * fmc = 0;
extension_model_converter * xmc = 0;
if (m_produce_models) {
fmc = alloc(filter_model_converter, m);
xmc = alloc(extension_model_converter, m);
mc = concat(fmc, xmc);
}
obj_map<app, rational>::iterator it = m_var2degree.begin();
obj_map<app, rational>::iterator end = m_var2degree.end();
for (; it != end; ++it) {
SASSERT(it->m_value.is_int());
SASSERT(it->m_value >= rational(2));
app * fresh = m.mk_fresh_const(0, it->m_key->get_decl()->get_range());
m_pinned.push_back(fresh);
m_var2var.insert(it->m_key, fresh);
if (m_produce_models) {
fmc->insert(fresh->get_decl());
xmc->insert(it->m_key->get_decl(), mk_power(fresh, rational(1)/it->m_value));
}
if (m_produce_proofs) {
expr * s = mk_power(it->m_key, it->m_value);
expr * eq = m.mk_eq(fresh, s);
proof * pr1 = m.mk_def_intro(eq);
proof * result_pr = m.mk_apply_def(fresh, s, pr1);
m_pinned.push_back(result_pr);
m_var2pr.insert(it->m_key, result_pr);
}
}
}
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());
mc = 0; pc = 0; core = 0;
m_produce_proofs = g->proofs_enabled();
m_produce_models = g->models_enabled();
tactic_report report("degree_shift", *g);
collect(*g);
discard_non_candidates();
if (!m_var2degree.empty()) {
prepare_substitution(mc);
m_rw = alloc(rw, *this);
// substitute
expr_ref new_curr(m);
proof_ref new_pr(m);
unsigned size = g->size();
for (unsigned idx = 0; idx < size; idx++) {
checkpoint();
expr * curr = g->form(idx);
(*m_rw)(curr, new_curr, new_pr);
if (m_produce_proofs) {
proof * pr = g->pr(idx);
new_pr = m.mk_modus_ponens(pr, new_pr);
}
g->update(idx, new_curr, new_pr, g->dep(idx));
}
// add >= 0 constraints for variables with even degree
obj_map<app, rational>::iterator it = m_var2degree.begin();
obj_map<app, rational>::iterator end = m_var2degree.end();
for (; it != end; ++it) {
SASSERT(it->m_value.is_int());
SASSERT(it->m_value >= rational(2));
if (it->m_value.is_even()) {
app * new_var = m_var2var.find(it->m_key);
app * new_c = m_autil.mk_ge(new_var, m_autil.mk_numeral(rational(0), false));
proof * new_pr = 0;
if (m_produce_proofs) {
proof * pr = m_var2pr.find(it->m_key);
new_pr = m.mk_th_lemma(m_autil.get_family_id(), new_c, 1, &pr);
}
g->assert_expr(new_c, new_pr, 0);
}
}
}
g->inc_depth();
result.push_back(g.get());
TRACE("degree_shift", g->display(tout); if (mc) mc->display(tout););
SASSERT(g->is_well_sorted());
}
};
imp * m_imp;
public:
degree_shift_tactic(ast_manager & m) {
m_imp = alloc(imp, m);
}
virtual tactic * translate(ast_manager & m) {
return alloc(degree_shift_tactic, m);
}
virtual ~degree_shift_tactic() {
dealloc(m_imp);
}
virtual void operator()(goal_ref const & in,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
(*m_imp)(in, result, mc, pc, core);
}
virtual void cleanup() {
ast_manager & m = m_imp->m;
imp * d = m_imp;
#pragma omp critical (tactic_cancel)
{
m_imp = 0;
}
dealloc(d);
d = alloc(imp, m);
#pragma omp critical (tactic_cancel)
{
m_imp = d;
}
}
protected:
virtual void set_cancel(bool f) {
if (m_imp)
m_imp->set_cancel(f);
}
};
tactic * mk_degree_shift_tactic(ast_manager & m, params_ref const & p) {
params_ref mul2power_p;
mul2power_p.set_bool(":mul-to-power", true);
return and_then(using_params(mk_simplify_tactic(m), mul2power_p),
clean(alloc(degree_shift_tactic, m)));
}

View file

@ -0,0 +1,31 @@
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
degree_shift_tactic.h
Abstract:
Simple degree shift procedure.
Basic idea: if goal G contains a real variable x, x occurs with degrees
d_1, ..., d_k in G, and n = gcd(d_1, ..., d_k) > 1.
Then, replace x^n with a new fresh variable y.
Author:
Leonardo de Moura (leonardo) 2011-12-30.
Revision History:
--*/
#ifndef _DEGREE_SHIFT_TACTIC_H_
#define _DEGREE_SHIFT_TACTIC_H_
#include"params.h"
class ast_manager;
class tactic;
tactic * mk_degree_shift_tactic(ast_manager & m, params_ref const & p = params_ref());
#endif

View file

@ -0,0 +1,429 @@
/*++
Copyright (c) 2012 Microsoft Corporation
Module Name:
diff_neq_tactic.cpp
Abstract:
Solver for integer problems that contains literals of the form
k <= x
x <= k
x - y != k
And all variables are bounded.
Author:
Leonardo de Moura (leonardo) 2012-02-07.
Revision History:
--*/
#include"tactical.h"
#include"arith_decl_plugin.h"
#include"ast_smt2_pp.h"
#include"model.h"
class diff_neq_tactic : public tactic {
struct imp {
ast_manager & m;
arith_util u;
typedef unsigned var;
expr_ref_vector m_var2expr;
obj_map<expr, var> m_expr2var;
svector<int> m_lower;
svector<int> m_upper;
struct diseq {
var m_y;
int m_k;
diseq(var y, int k):m_y(y), m_k(k) {}
};
typedef svector<diseq> diseqs;
vector<diseqs> m_var_diseqs;
typedef svector<int> decision_stack;
decision_stack m_stack;
volatile bool m_cancel;
bool m_produce_models;
rational m_max_k;
rational m_max_neg_k;
unsigned m_num_conflicts;
imp(ast_manager & _m, params_ref const & p):
m(_m),
u(m),
m_var2expr(m) {
updt_params(p);
m_cancel = false;
}
void updt_params(params_ref const & p) {
m_max_k = rational(p.get_uint(":diff-neq-max-k", 1024));
m_max_neg_k = -m_max_k;
if (m_max_k >= rational(INT_MAX/2))
m_max_k = rational(INT_MAX/2);
}
void set_cancel(bool f) {
m_cancel = f;
}
void throw_not_supported() {
throw tactic_exception("goal is not diff neq");
}
unsigned num_vars() const {
return m_upper.size();
}
var mk_var(expr * t) {
SASSERT(is_uninterp_const(t));
var x;
if (m_expr2var.find(t, x))
return x;
x = m_upper.size();
m_expr2var.insert(t, x);
m_var2expr.push_back(t);
m_lower.push_back(INT_MIN); // unknown
m_upper.push_back(INT_MAX); // unknown
m_var_diseqs.push_back(diseqs());
return x;
}
void process_le(expr * lhs, expr * rhs) {
if (!u.is_int(lhs))
throw_not_supported();
rational k;
if (is_uninterp_const(lhs) && u.is_numeral(rhs, k) && m_max_neg_k <= k && k <= m_max_k) {
var x = mk_var(lhs);
int _k = static_cast<int>(k.get_int64());
m_upper[x] = _k;
}
else if (is_uninterp_const(rhs) && u.is_numeral(lhs, k) && m_max_neg_k <= k && k <= m_max_k) {
var x = mk_var(rhs);
int _k = static_cast<int>(k.get_int64());
m_lower[x] = _k;
}
else {
throw_not_supported();
}
}
// process t1 - t2 != k
void process_neq_core(expr * t1, expr * t2, int k) {
var x1 = mk_var(t1);
var x2 = mk_var(t2);
if (x1 == x2)
throw_not_supported(); // must simplify first
if (x1 < x2) {
std::swap(x1, x2);
k = -k;
}
m_var_diseqs[x1].push_back(diseq(x2, k));
}
void process_neq(expr * lhs, expr * rhs) {
if (!u.is_int(lhs))
throw_not_supported();
if (is_uninterp_const(lhs) && is_uninterp_const(rhs)) {
process_neq_core(lhs, rhs, 0);
return;
}
if (u.is_numeral(lhs))
std::swap(lhs, rhs);
rational k;
if (!u.is_numeral(rhs, k))
throw_not_supported();
if (!(m_max_neg_k <= k && k <= m_max_k))
throw_not_supported();
int _k = static_cast<int>(k.get_int64());
expr * t1, * t2, * mt1, * mt2;
if (u.is_add(lhs, t1, t2)) {
if (is_uninterp_const(t1) && u.is_times_minus_one(t2, mt2) && is_uninterp_const(mt2))
process_neq_core(t1, mt2, _k);
else if (is_uninterp_const(t2) && u.is_times_minus_one(t1, mt1) && is_uninterp_const(mt1))
process_neq_core(t2, mt1, _k);
else
throw_not_supported();
}
else {
throw_not_supported();
}
}
// throws exception if contains unbounded variable
void check_unbounded() {
unsigned num = num_vars();
for (var x = 0; x < num; x++) {
if (m_lower[x] == INT_MIN || m_upper[x] == INT_MAX)
throw_not_supported();
// possible extension: support bound normalization here
if (m_lower[x] != 0)
throw_not_supported(); // use bound normalizer
}
}
void compile(goal const & g) {
expr * lhs;
expr * rhs;
unsigned sz = g.size();
for (unsigned i = 0; i < sz; i++) {
expr * f = g.form(i);
TRACE("diff_neq_tactic", tout << "processing: " << mk_ismt2_pp(f, m) << "\n";);
if (u.is_le(f, lhs, rhs))
process_le(lhs, rhs);
else if (u.is_ge(f, lhs, rhs))
process_le(rhs, lhs);
else if (m.is_not(f, f) && m.is_eq(f, lhs, rhs))
process_neq(lhs, rhs);
else
throw_not_supported();
}
check_unbounded();
}
void display(std::ostream & out) {
unsigned num = num_vars();
for (var x = 0; x < num; x++) {
out << m_lower[x] << " <= " << mk_ismt2_pp(m_var2expr.get(x), m) << " <= " << m_upper[x] << "\n";
}
for (var x = 0; x < num; x++) {
diseqs::iterator it = m_var_diseqs[x].begin();
diseqs::iterator end = m_var_diseqs[x].end();
for (; it != end; ++it) {
out << mk_ismt2_pp(m_var2expr.get(x), m) << " != " << mk_ismt2_pp(m_var2expr.get(it->m_y), m) << " + " << it->m_k << "\n";
}
}
}
void display_model(std::ostream & out) {
unsigned num = m_stack.size();
for (var x = 0; x < num; x++) {
out << mk_ismt2_pp(m_var2expr.get(x), m) << " := " << m_stack[x] << "\n";
}
}
svector<bool> m_forbidden;
// make sure m_forbidden.size() > max upper bound
void init_forbidden() {
int max = 0;
unsigned num = num_vars();
for (var x = 0; x < num; x++) {
if (m_upper[x] > max)
max = m_upper[x];
}
m_forbidden.reset();
m_forbidden.resize(max+1, false);
}
// Return a value v s.t. v >= starting_at and v <= m_upper[x] and all diseqs in m_var_diseqs[x] are satisfied.
// Return -1 if such value does not exist.
int choose_value(var x, int starting_at) {
int max = starting_at-1;
int v = starting_at;
int upper = m_upper[x];
if (starting_at > upper)
return -1;
diseqs const & ds = m_var_diseqs[x];
diseqs::const_iterator it = ds.begin();
diseqs::const_iterator end = ds.end();
for (; it != end; ++it) {
int bad_v = m_stack[it->m_y] + it->m_k;
if (bad_v < v)
continue;
if (bad_v > upper)
continue;
if (bad_v == v) {
while (true) {
v++;
if (v > upper)
return -1;
if (!m_forbidden[v])
break;
m_forbidden[v] = false;
}
continue;
}
SASSERT(bad_v > v && bad_v <= upper);
m_forbidden[bad_v] = true;
if (bad_v > max)
max = bad_v;
}
// reset forbidden
for (int i = starting_at + 1; i <= max; i++)
m_forbidden[i] = false;
DEBUG_CODE({
for (unsigned i = 0; i < m_forbidden.size(); i++) {
SASSERT(!m_forbidden[i]);
}
});
return v;
}
bool extend_model(var x) {
int v = choose_value(x, 0);
if (v == -1)
return false;
m_stack.push_back(v);
return true;
}
bool resolve_conflict() {
m_num_conflicts++;
while (!m_stack.empty()) {
int v = m_stack.back();
m_stack.pop_back();
var x = m_stack.size();
v = choose_value(x, v+1);
if (v != -1) {
m_stack.push_back(v);
return true;
}
}
return false;
}
bool search() {
m_num_conflicts = 0;
init_forbidden();
unsigned nvars = num_vars();
while (m_stack.size() < nvars) {
if (m_cancel)
throw tactic_exception(TACTIC_CANCELED_MSG);
TRACE("diff_neq_tactic", display_model(tout););
var x = m_stack.size();
if (extend_model(x))
continue;
if (!resolve_conflict())
return false;
}
TRACE("diff_neq_tactic", display_model(tout););
return true;
}
model * mk_model() {
model * md = alloc(model, m);
unsigned num = num_vars();
SASSERT(m_stack.size() == num);
for (var x = 0; x < num; x++) {
func_decl * d = to_app(m_var2expr.get(x))->get_decl();
md->register_decl(d, u.mk_numeral(rational(m_stack[x]), true));
}
return md;
}
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());
m_produce_models = g->models_enabled();
mc = 0; pc = 0; core = 0; result.reset();
tactic_report report("diff-neq", *g);
fail_if_proof_generation("diff-neq", g);
fail_if_unsat_core_generation("diff-neq", g);
if (g->inconsistent()) {
result.push_back(g.get());
return;
}
compile(*g);
TRACE("diff_neq_tactic", g->display(tout); display(tout););
bool r = search();
report_tactic_progress(":conflicts", m_num_conflicts);
if (r) {
if (m_produce_models)
mc = model2model_converter(mk_model());
g->reset();
}
else {
g->assert_expr(m.mk_false());
}
g->inc_depth();
result.push_back(g.get());
TRACE("diff_neq", g->display(tout););
SASSERT(g->is_well_sorted());
}
};
imp * m_imp;
params_ref m_params;
public:
diff_neq_tactic(ast_manager & m, params_ref const & p):
m_params(p) {
m_imp = alloc(imp, m, p);
}
virtual tactic * translate(ast_manager & m) {
return alloc(diff_neq_tactic, m, m_params);
}
virtual ~diff_neq_tactic() {
dealloc(m_imp);
}
virtual void updt_params(params_ref const & p) {
m_params = p;
m_imp->updt_params(p);
}
virtual void collect_param_descrs(param_descrs & r) {
r.insert(":diff-neq-max-k", CPK_UINT, "(default: 1024) maximum variable upper bound for diff neq solver.");
}
virtual void collect_statistics(statistics & st) const {
st.update("conflicts", m_imp->m_num_conflicts);
}
virtual void reset_statistics() {
m_imp->m_num_conflicts = 0;
}
/**
\brief Fix a DL variable in s to 0.
If s is not really in the difference logic fragment, then this is a NOOP.
*/
virtual void operator()(goal_ref const & in,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
(*m_imp)(in, result, mc, pc, core);
}
virtual void cleanup() {
unsigned num_conflicts = m_imp->m_num_conflicts;
ast_manager & m = m_imp->m;
imp * d = m_imp;
#pragma omp critical (tactic_cancel)
{
d = m_imp;
}
dealloc(d);
d = alloc(imp, m, m_params);
#pragma omp critical (tactic_cancel)
{
m_imp = d;
}
m_imp->m_num_conflicts = num_conflicts;
}
protected:
virtual void set_cancel(bool f) {
if (m_imp)
m_imp->set_cancel(f);
}
};
tactic * mk_diff_neq_tactic(ast_manager & m, params_ref const & p) {
return clean(alloc(diff_neq_tactic, m, p));
}

View file

@ -0,0 +1,32 @@
/*++
Copyright (c) 2012 Microsoft Corporation
Module Name:
diff_neq_tactic.h
Abstract:
Solver for integer problems that contains literals of the form
k <= x
x <= k
x - y != k
And all variables are bounded.
Author:
Leonardo de Moura (leonardo) 2012-02-07.
Revision History:
--*/
#ifndef _DIFF_NEQ_TACTIC_H_
#define _DIFF_NEQ_TACTIC_H_
#include"params.h"
class ast_manager;
class tactic;
tactic * mk_diff_neq_tactic(ast_manager & m, params_ref const & p = params_ref());
#endif

View file

@ -0,0 +1,358 @@
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
fix_dl_var_tactic.cpp
Abstract:
Fix a difference logic variable to 0.
If the problem is in the difference logic fragment, that is, all arithmetic terms
are of the form (x + k), and the arithmetic atoms are of the
form x - y <= k or x - y = k. Then, we can set one variable to 0.
This is useful because, many bounds can be exposed after this operation is performed.
Author:
Leonardo de Moura (leonardo) 2011-12-19
Revision History:
--*/
#include"tactical.h"
#include"th_rewriter.h"
#include"extension_model_converter.h"
#include"arith_decl_plugin.h"
#include"expr_substitution.h"
#include"ast_smt2_pp.h"
class fix_dl_var_tactic : public tactic {
struct is_target {
struct failed {};
ast_manager & m;
arith_util & m_util;
expr_fast_mark1 * m_visited;
ptr_vector<expr> m_todo;
obj_map<app, unsigned> m_occs;
obj_map<app, unsigned> m_non_nested_occs;
is_target(arith_util & u):
m(u.get_manager()),
m_util(u) {
}
void throw_failed(expr * ctx1, expr * ctx2 = 0) {
TRACE("fix_dl_var", tout << mk_ismt2_pp(ctx1, m) << "\n"; if (ctx2) tout << mk_ismt2_pp(ctx2, m) << "\n";);
throw failed();
}
bool is_arith(expr * n) {
sort * s = m.get_sort(n);
return s->get_family_id() == m_util.get_family_id();
}
// Return true if n is uninterpreted with respect to arithmetic.
bool is_uninterp(expr * n) {
return is_app(n) && to_app(n)->get_family_id() != m_util.get_family_id();
}
// Remark: we say an expression is nested, if it occurs inside the boolean structure of the formula.
// That is, the expression is not part of an unit clause comprising of a single inequality/equality.
void inc_occ(expr * n, bool nested) {
if (is_uninterp_const(n) && is_arith(n)) {
obj_map<app, unsigned>::obj_map_entry * entry = m_occs.insert_if_not_there2(to_app(n), 0);
entry->get_data().m_value++;
if (!nested) {
entry = m_non_nested_occs.insert_if_not_there2(to_app(n), 0);
entry->get_data().m_value++;
}
}
}
void visit(expr * n, bool nested) {
inc_occ(n, nested);
if (!m_visited->is_marked(n)) {
m_visited->mark(n);
m_todo.push_back(n);
}
}
void process_app(app * t) {
unsigned num = t->get_num_args();
for (unsigned i = 0; i < num; i++)
visit(t->get_arg(i), false);
}
void process_arith_atom(expr * lhs, expr * rhs, bool nested) {
if (is_uninterp(lhs) && is_uninterp(rhs)) {
visit(lhs, nested);
visit(rhs, nested);
return;
}
if (m_util.is_numeral(lhs))
std::swap(lhs, rhs);
if (!m_util.is_numeral(rhs))
throw_failed(lhs, rhs);
expr * t, * ms, * s;
// check if lhs is of the form: (+ t (* (- 1) s))
if (m_util.is_add(lhs, t, ms) && m_util.is_times_minus_one(ms, s) && is_uninterp(t) && is_uninterp(s)) {
visit(t, nested);
visit(s, nested);
}
else {
CTRACE("fix_dl_var", m_util.is_add(lhs, t, ms),
s = 0;
tout << "is_times_minus_one: " << m_util.is_times_minus_one(ms, s) << "\n";
tout << "is_uninterp(t): " << is_uninterp(t) << "\n";
tout << "t.family_id(): " << (is_app(t) ? to_app(t)->get_family_id() : -1) << "\n";
tout << "util.family_id: " << m_util.get_family_id() << "\n";
if (s) {
tout << "is_uninterp(s): " << is_uninterp(s) << "\n";
tout << "s.family_id(): " << (is_app(s) ? to_app(s)->get_family_id() : -1) << "\n";
});
throw_failed(lhs, rhs);
}
}
void process_eq(app * t, bool nested) {
if (!is_arith(t->get_arg(0))) {
process_app(t);
return;
}
process_arith_atom(t->get_arg(0), t->get_arg(1), nested);
}
void process_arith(app * t, bool nested) {
if (m.is_bool(t)) {
process_arith_atom(t->get_arg(0), t->get_arg(1), nested);
return;
}
// check if t is of the form c + k
expr * c, * k;
if (m_util.is_add(t, k, c) && is_uninterp(c) && m_util.is_numeral(k)) {
visit(c, nested);
}
else {
throw_failed(t);
}
}
void process(expr * n) {
if (m_visited->is_marked(n))
return;
while (m.is_not(n, n))
;
if (is_app(n) && to_app(n)->get_family_id() == m_util.get_family_id()) {
process_arith(to_app(n), false);
return;
}
m_todo.push_back(n);
m_visited->mark(n);
while (!m_todo.empty()) {
expr * n = m_todo.back();
m_todo.pop_back();
if (!is_app(n))
throw_failed(n);
app * t = to_app(n);
if (m.is_eq(t))
process_eq(t, true);
else if (t->get_family_id() == m_util.get_family_id())
process_arith(t, true);
else
process_app(t);
}
}
app * most_occs(obj_map<app, unsigned> & occs, unsigned & best) {
app * r = 0;
best = 0;
obj_map<app, unsigned>::iterator it = occs.begin();
obj_map<app, unsigned>::iterator end = occs.end();
for (; it != end; ++it) {
if (it->m_value > best) {
best = it->m_value;
r = it->m_key;
}
}
return r;
}
// TODO make it a parameter
#define NESTED_PENALTY 10
app * most_occs() {
// We try to choose a variable that when set to 0 will generate many bounded variables.
// That is why we give preference to variables occuring in non-nested inequalities.
unsigned best1, best2;
app * r1, * r2;
r1 = most_occs(m_non_nested_occs, best1);
r2 = most_occs(m_occs, best2);
TRACE("fix_dl_var_choice",
if (r1) {
tout << "r1 occs: " << best1 << "\n";
tout << mk_ismt2_pp(r1, m) << "\n";
}
if (r2) {
tout << "r2 occs: " << best2 << "\n";
tout << mk_ismt2_pp(r2, m) << "\n";
});
if (best2 > NESTED_PENALTY * best1)
return r2;
else
return r1;
}
app * operator()(goal const & g) {
try {
expr_fast_mark1 visited;
m_visited = &visited;
unsigned sz = g.size();
for (unsigned i = 0; i < sz; i++) {
process(g.form(i));
}
return most_occs();
}
catch (failed) {
return 0;
}
}
};
struct imp {
ast_manager & m;
arith_util u;
th_rewriter m_rw;
bool m_produce_models;
imp(ast_manager & _m, params_ref const & p):
m(_m),
u(m),
m_rw(m, p) {
}
void updt_params(params_ref const & p) {
m_rw.updt_params(p);
}
void set_cancel(bool f) {
m_rw.set_cancel(f);
}
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());
mc = 0; pc = 0; core = 0;
tactic_report report("fix-dl-var", *g);
bool produce_proofs = g->proofs_enabled();
m_produce_models = g->models_enabled();
app * var = is_target(u)(*g);
if (var != 0) {
IF_VERBOSE(TACTIC_VERBOSITY_LVL, verbose_stream() << "(fixing-at-zero " << var->get_decl()->get_name() << ")\n";);
tactic_report report("fix-dl-var", *g);
expr_substitution subst(m);
app * zero = u.mk_numeral(rational(0), u.is_int(var));
subst.insert(var, zero);
m_rw.set_substitution(&subst);
if (m_produce_models) {
extension_model_converter * _mc = alloc(extension_model_converter, m);
_mc->insert(var->get_decl(), zero);
mc = _mc;
}
expr_ref new_curr(m);
proof_ref new_pr(m);
unsigned size = g->size();
for (unsigned idx = 0; idx < size; idx++) {
expr * curr = g->form(idx);
m_rw(curr, new_curr, new_pr);
if (produce_proofs) {
proof * pr = g->pr(idx);
new_pr = m.mk_modus_ponens(pr, new_pr);
}
g->update(idx, new_curr, new_pr, g->dep(idx));
}
g->inc_depth();
}
result.push_back(g.get());
TRACE("fix_dl_var", g->display(tout););
SASSERT(g->is_well_sorted());
}
};
imp * m_imp;
params_ref m_params;
public:
fix_dl_var_tactic(ast_manager & m, params_ref const & p):
m_params(p) {
m_imp = alloc(imp, m, p);
}
virtual tactic * translate(ast_manager & m) {
return alloc(fix_dl_var_tactic, m, m_params);
}
virtual ~fix_dl_var_tactic() {
dealloc(m_imp);
}
virtual void updt_params(params_ref const & p) {
m_params = p;
m_imp->updt_params(p);
}
virtual void collect_param_descrs(param_descrs & r) {
th_rewriter::get_param_descrs(r);
}
virtual void operator()(goal_ref const & in,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
(*m_imp)(in, result, mc, pc, core);
}
virtual void cleanup() {
ast_manager & m = m_imp->m;
imp * d = m_imp;
#pragma omp critical (tactic_cancel)
{
m_imp = 0;
}
dealloc(d);
d = alloc(imp, m, m_params);
#pragma omp critical (tactic_cancel)
{
m_imp = d;
}
}
virtual void set_cancel(bool f) {
if (m_imp)
m_imp->set_cancel(f);
}
};
tactic * mk_fix_dl_var_tactic(ast_manager & m, params_ref const & p) {
return clean(alloc(fix_dl_var_tactic, m, p));
}

View file

@ -0,0 +1,33 @@
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
fix_dl_var_tactic.h
Abstract:
Fix a difference logic variable to 0.
If the problem is in the difference logic fragment, that is, all arithmetic terms
are of the form (x + k), and the arithmetic atoms are of the
form x - y <= k or x - y = k. Then, we can set one variable to 0.
This is useful because, many bounds can be exposed after this operation is performed.
Author:
Leonardo (leonardo) 2011-12-29
Notes:
--*/
#ifndef _FIX_DL_VAR_TACTIC_H_
#define _FIX_DL_VAR_TACTIC_H_
#include"params.h"
class ast_manager;
class tactic;
tactic * mk_fix_dl_var_tactic(ast_manager & m, params_ref const & p = params_ref());
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,33 @@
/*++
Copyright (c) 2012 Microsoft Corporation
Module Name:
fm_tactic.h
Abstract:
Use Fourier-Motzkin to eliminate variables.
This strategy can handle conditional bounds
(i.e., clauses with at most one constraint).
The strategy mk_occf can be used to put the
formula in OCC form.
Author:
Leonardo de Moura (leonardo) 2012-02-04.
Revision History:
--*/
#ifndef _FM_TACTIC_H_
#define _FM_TACTIC_H_
#include"params.h"
class ast_manager;
class tactic;
tactic * mk_fm_tactic(ast_manager & m, params_ref const & p = params_ref());
#endif

View file

@ -0,0 +1,366 @@
/*++
Copyright (c) 2012 Microsoft Corporation
Module Name:
lia2pb_tactic.cpp
Abstract:
Reduce bounded LIA benchmark into 0-1 LIA benchmark.
Author:
Leonardo de Moura (leonardo) 2012-02-07.
Revision History:
--*/
#include"tactical.h"
#include"bound_manager.h"
#include"th_rewriter.h"
#include"for_each_expr.h"
#include"extension_model_converter.h"
#include"filter_model_converter.h"
#include"arith_decl_plugin.h"
#include"expr_substitution.h"
#include"ast_smt2_pp.h"
class lia2pb_tactic : public tactic {
struct imp {
ast_manager & m;
bound_manager m_bm;
arith_util m_util;
expr_dependency_ref_vector m_new_deps;
th_rewriter m_rw;
bool m_produce_models;
bool m_produce_unsat_cores;
bool m_partial_lia2pb;
unsigned m_max_bits;
unsigned m_total_bits;
imp(ast_manager & _m, params_ref const & p):
m(_m),
m_bm(m),
m_util(m),
m_new_deps(m),
m_rw(m, p) {
updt_params(p);
}
void updt_params_core(params_ref const & p) {
m_partial_lia2pb = p.get_bool(":lia2pb-partial", false);
m_max_bits = p.get_uint(":lia2pb-max-bits", 32);
m_total_bits = p.get_uint(":lia2pb-total-bits", 2048);
}
void updt_params(params_ref const & p) {
m_rw.updt_params(p);
updt_params_core(p);
}
void set_cancel(bool f) {
m_rw.set_cancel(f);
}
bool is_target_core(expr * n, rational & u) {
if (!is_uninterp_const(n))
return false;
rational l; bool s;
if (m_bm.has_lower(n, l, s) &&
m_bm.has_upper(n, u, s) &&
l.is_zero() &&
u.get_num_bits() <= m_max_bits) {
return true;
}
return false;
}
bool is_bounded(expr * n) {
rational u;
return is_target_core(n, u);
}
bool is_target(expr * n) {
rational u;
return is_target_core(n, u) && u > rational(1);
}
struct failed {};
struct visitor {
imp & m_owner;
visitor(imp & o):m_owner(o) {}
void throw_failed(expr * n) {
TRACE("lia2pb", tout << "Failed at:\n" << mk_ismt2_pp(n, m_owner.m) << "\n";);
throw failed();
}
void operator()(var * n) {
throw_failed(n);
}
void operator()(app * n) {
family_id fid = n->get_family_id();
if (fid == m_owner.m.get_basic_family_id()) {
// all basic family ops are OK
}
else if (fid == m_owner.m_util.get_family_id()) {
// check if linear
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_failed(n);
if (!m_owner.m_util.is_numeral(n->get_arg(0)))
throw_failed(n);
return;
default:
throw_failed(n);
}
}
else if (is_uninterp_const(n)) {
if (m_owner.m_util.is_real(n)) {
if (!m_owner.m_partial_lia2pb)
throw_failed(n);
}
else if (m_owner.m_util.is_int(n)) {
if (!m_owner.m_partial_lia2pb && !m_owner.is_bounded(n))
throw_failed(n);
}
}
else {
sort * s = m_owner.m.get_sort(n);
if (s->get_family_id() == m_owner.m_util.get_family_id())
throw_failed(n);
}
}
void operator()(quantifier * n) {
throw_failed(n);
}
};
bool check(goal const & g) {
try {
expr_fast_mark1 visited;
visitor proc(*this);
unsigned sz = g.size();
for (unsigned i = 0; i < sz; i++) {
expr * f = g.form(i);
for_each_expr_core<visitor, expr_fast_mark1, true, true>(proc, visited, f);
}
return true;
}
catch (failed) {
return false;
}
}
bool has_target() {
bound_manager::iterator it = m_bm.begin();
bound_manager::iterator end = m_bm.end();
for (; it != end; ++it) {
if (is_target(*it))
return true;
}
return false;
}
bool check_num_bits() {
unsigned num_bits = 0;
rational u;
bound_manager::iterator it = m_bm.begin();
bound_manager::iterator end = m_bm.end();
for (; it != end; ++it) {
expr * x = *it;
if (is_target_core(x, u) && u > rational(1)) {
num_bits += u.get_num_bits();
if (num_bits > m_total_bits)
return false;
}
}
return true;
}
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());
fail_if_proof_generation("lia2pb", g);
m_produce_models = g->models_enabled();
m_produce_unsat_cores = g->unsat_core_enabled();
mc = 0; pc = 0; core = 0; result.reset();
tactic_report report("lia2pb", *g);
m_bm.reset(); m_rw.reset(); m_new_deps.reset();
if (g->inconsistent()) {
result.push_back(g.get());
return;
}
m_bm(*g);
TRACE("lia2pb", m_bm.display(tout););
// check if there is some variable to be converted
if (!has_target()) {
// nothing to be done
g->inc_depth();
result.push_back(g.get());
return;
}
if (!check(*g))
throw tactic_exception("goal is in a fragment unsupported by lia2pb");
if (!check_num_bits())
throw tactic_exception("lia2pb failed, number of necessary bits exceeds specified threshold (use option :lia2pb-total-bits to increase threshold)");
extension_model_converter * mc1 = 0;
filter_model_converter * mc2 = 0;
if (m_produce_models) {
mc1 = alloc(extension_model_converter, m);
mc2 = alloc(filter_model_converter, m);
mc = concat(mc2, mc1);
}
expr_ref zero(m);
expr_ref one(m);
zero = m_util.mk_numeral(rational(0), true);
one = m_util.mk_numeral(rational(1), true);
unsigned num_converted = 0;
expr_substitution subst(m, m_produce_unsat_cores, false);
rational u;
ptr_buffer<expr> def_args;
bound_manager::iterator it = m_bm.begin();
bound_manager::iterator end = m_bm.end();
for (; it != end; ++it) {
expr * x = *it;
if (is_target_core(x, u) && u > rational(1)) {
num_converted++;
def_args.reset();
rational a(1);
unsigned num_bits = u.get_num_bits();
for (unsigned i = 0; i < num_bits; i++) {
app * x_prime = m.mk_fresh_const(0, m_util.mk_int());
g->assert_expr(m_util.mk_le(zero, x_prime));
g->assert_expr(m_util.mk_le(x_prime, one));
if (a.is_one())
def_args.push_back(x_prime);
else
def_args.push_back(m_util.mk_mul(m_util.mk_numeral(a, true), x_prime));
if (m_produce_models)
mc2->insert(x_prime->get_decl());
a *= rational(2);
}
SASSERT(def_args.size() > 1);
expr * def = m_util.mk_add(def_args.size(), def_args.c_ptr());
expr_dependency * dep = 0;
if (m_produce_unsat_cores) {
dep = m.mk_join(m_bm.lower_dep(x), m_bm.upper_dep(x));
if (dep != 0)
m_new_deps.push_back(dep);
}
TRACE("lia2pb", tout << mk_ismt2_pp(x, m) << " -> " << dep << "\n";);
subst.insert(x, def, 0, dep);
if (m_produce_models)
mc1->insert(to_app(x)->get_decl(), def);
}
}
report_tactic_progress(":converted-lia2pb", num_converted);
m_rw.set_substitution(&subst);
expr_ref new_curr(m);
proof_ref new_pr(m);
unsigned size = g->size();
for (unsigned idx = 0; idx < size; idx++) {
expr * curr = g->form(idx);
expr_dependency * dep = 0;
m_rw(curr, new_curr, new_pr);
if (m_produce_unsat_cores) {
dep = m.mk_join(m_rw.get_used_dependencies(), g->dep(idx));
m_rw.reset_used_dependencies();
}
g->update(idx, new_curr, 0, dep);
}
g->inc_depth();
result.push_back(g.get());
TRACE("lia2pb", g->display(tout););
SASSERT(g->is_well_sorted());
}
};
imp * m_imp;
params_ref m_params;
public:
lia2pb_tactic(ast_manager & m, params_ref const & p):
m_params(p) {
m_imp = alloc(imp, m, p);
}
virtual tactic * translate(ast_manager & m) {
return alloc(lia2pb_tactic, m, m_params);
}
virtual ~lia2pb_tactic() {
dealloc(m_imp);
}
virtual void updt_params(params_ref const & p) {
m_params = p;
m_imp->updt_params(p);
}
virtual void collect_param_descrs(param_descrs & r) {
r.insert(":lia2pb-partial", CPK_BOOL, "(default: false) partial lia2pb conversion.");
r.insert(":lia2pb-max-bits", CPK_UINT, "(default: 32) maximum number of bits to be used (per variable) in lia2pb.");
r.insert(":lia2pb-total-bits", CPK_UINT, "(default: 2048) total number of bits to be used (per problem) in lia2pb.");
}
virtual void operator()(goal_ref const & in,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
(*m_imp)(in, result, mc, pc, core);
}
virtual void cleanup() {
ast_manager & m = m_imp->m;
imp * d = m_imp;
#pragma omp critical (tactic_cancel)
{
d = m_imp;
}
dealloc(d);
d = alloc(imp, m, m_params);
#pragma omp critical (tactic_cancel)
{
m_imp = d;
}
}
protected:
virtual void set_cancel(bool f) {
if (m_imp)
m_imp->set_cancel(f);
}
};
tactic * mk_lia2pb_tactic(ast_manager & m, params_ref const & p) {
return clean(alloc(lia2pb_tactic, m, p));
}

View file

@ -0,0 +1,28 @@
/*++
Copyright (c) 2012 Microsoft Corporation
Module Name:
lia2pb_tactic.h
Abstract:
Reduce bounded LIA benchmark into 0-1 LIA benchmark.
Author:
Leonardo de Moura (leonardo) 2012-02-07.
Revision History:
--*/
#ifndef _LIA2PB_TACTIC_H_
#define _LIA2PB_TACTIC_H_
#include"params.h"
class ast_manager;
class tactic;
tactic * mk_lia2pb_tactic(ast_manager & m, params_ref const & p = params_ref());
#endif

View file

@ -0,0 +1,279 @@
/*++
Copyright (c) 2006 Microsoft Corporation
Module Name:
linear_equation.cpp
Abstract:
Basic infrastructure for managing linear equations of the form:
a_1 * x_1 + ... + a_n * x_n = 0
Author:
Leonardo de Moura (leonardo) 2011-06-28
Revision History:
--*/
#include"linear_equation.h"
/**
\brief Return the position of variable x_i in the linear equation.
Return UINT_MAX, if the variable is not in the linear_equation.
*/
unsigned linear_equation::pos(unsigned x_i) const {
int low = 0;
int high = m_size - 1;
while (true) {
int mid = low + ((high - low) / 2);
var x_mid = m_xs[mid];
if (x_i > x_mid) {
low = mid + 1;
if (low > high)
return UINT_MAX;
}
else if (x_i < x_mid) {
high = mid - 1;
if (low > high)
return UINT_MAX;
}
else {
return mid;
}
}
}
void linear_equation_manager::display(std::ostream & out, linear_equation const & eq) const {
unsigned sz = eq.m_size;
for (unsigned i = 0; i < sz; i++) {
if (i > 0)
out << " + ";
out << m.to_string(eq.m_as[i]) << "*x" << eq.m_xs[i];
}
out << " = 0";
}
linear_equation * linear_equation_manager::mk(unsigned sz, mpq * as, var * xs, bool normalized) {
SASSERT(sz > 1);
// compute lcm of the denominators
mpz l;
mpz r;
m.set(l, as[0].denominator());
for (unsigned i = 1; i < sz; i++) {
m.set(r, as[i].denominator());
m.lcm(r, l, l);
}
TRACE("linear_equation_mk", tout << "lcm: " << m.to_string(l) << "\n";);
// copy l * as to m_int_buffer.
m_int_buffer.reset();
for (unsigned i = 0; i < sz; i++) {
TRACE("linear_equation_mk", tout << "before as[" << i << "]: " << m.to_string(as[i]) << "\n";);
m.mul(l, as[i], as[i]);
TRACE("linear_equation_mk", tout << "after as[" << i << "]: " << m.to_string(as[i]) << "\n";);
SASSERT(m.is_int(as[i]));
m_int_buffer.push_back(as[i].numerator());
}
linear_equation * new_eq = mk(sz, m_int_buffer.c_ptr(), xs, normalized);
m.del(r);
m.del(l);
return new_eq;
}
linear_equation * linear_equation_manager::mk_core(unsigned sz, mpz * as, var * xs) {
SASSERT(sz > 0);
DEBUG_CODE({
for (unsigned i = 1; i < sz; i++) {
SASSERT(xs[i-1] < xs[i]);
}
});
TRACE("linear_equation_bug", for (unsigned i = 0; i < sz; i++) tout << m.to_string(as[i]) << "*x" << xs[i] << " "; tout << "\n";);
mpz g;
m.set(g, as[0]);
for (unsigned i = 1; i < sz; i++) {
if (m.is_one(g))
break;
if (m.is_neg(as[i])) {
m.neg(as[i]);
m.gcd(g, as[i], g);
m.neg(as[i]);
}
else {
m.gcd(g, as[i], g);
}
}
if (!m.is_one(g)) {
for (unsigned i = 0; i < sz; i++) {
m.div(as[i], g, as[i]);
}
}
TRACE("linear_equation_bug",
tout << "g: " << m.to_string(g) << "\n";
for (unsigned i = 0; i < sz; i++) tout << m.to_string(as[i]) << "*x" << xs[i] << " "; tout << "\n";);
m.del(g);
unsigned obj_sz = linear_equation::get_obj_size(sz);
void * mem = m_allocator.allocate(obj_sz);
linear_equation * new_eq = new (mem) linear_equation();
mpz * new_as = reinterpret_cast<mpz*>(reinterpret_cast<char*>(new_eq) + sizeof(linear_equation));
double * new_app_as = reinterpret_cast<double*>(reinterpret_cast<char*>(new_as) + sz * sizeof(mpz));
var * new_xs = reinterpret_cast<var *>(reinterpret_cast<char*>(new_app_as) + sz * sizeof(double));
for (unsigned i = 0; i < sz; i++) {
new (new_as + i) mpz();
m.set(new_as[i], as[i]);
new_app_as[i] = m.get_double(as[i]);
var x_i = xs[i];
new_xs[i] = x_i;
}
new_eq->m_size = sz;
new_eq->m_as = new_as;
new_eq->m_approx_as = new_app_as;
new_eq->m_xs = new_xs;
return new_eq;
}
linear_equation * linear_equation_manager::mk(unsigned sz, mpz * as, var * xs, bool normalized) {
if (!normalized) {
for (unsigned i = 0; i < sz; i++) {
var x = xs[i];
m_mark.reserve(x+1, false);
m_val_buffer.reserve(x+1);
if (m_mark[x]) {
m.add(m_val_buffer[x], as[i], m_val_buffer[x]);
}
else {
m.set(m_val_buffer[x], as[i]);
m_mark[x] = true;
}
}
unsigned j = 0;
for (unsigned i = 0; i < sz; i++) {
var x = xs[i];
if (m_mark[x]) {
if (!m.is_zero(m_val_buffer[x])) {
xs[j] = xs[i];
m.set(as[j], m_val_buffer[x]);
j++;
}
m_mark[x] = false;
}
}
sz = j;
if (sz <= 1)
return 0;
}
else {
DEBUG_CODE({
for (unsigned i = 0; i < sz; i++) {
var x = xs[i];
m_mark.reserve(x+1, false);
SASSERT(!m_mark[x]);
m_mark[x] = true;
}
for (unsigned i = 0; i < sz; i++) {
var x = xs[i];
m_mark[x] = false;
}
});
}
for (unsigned i = 0; i < sz; i++) {
var x = xs[i];
m_val_buffer.reserve(x+1);
m.swap(m_val_buffer[x], as[i]);
}
std::sort(xs, xs+sz);
for (unsigned i = 0; i < sz; i++) {
var x = xs[i];
m.swap(as[i], m_val_buffer[x]);
}
return mk_core(sz, as, xs);
}
linear_equation * linear_equation_manager::mk(mpz const & b1, linear_equation const & eq1, mpz const & b2, linear_equation const & eq2) {
SASSERT(!m.is_zero(b1));
SASSERT(!m.is_zero(b2));
mpz tmp, new_a;
m_int_buffer.reset();
m_var_buffer.reset();
unsigned sz1 = eq1.size();
unsigned sz2 = eq2.size();
unsigned i1 = 0;
unsigned i2 = 0;
while (true) {
if (i1 == sz1) {
// copy remaining entries from eq2
while (i2 < sz2) {
m_int_buffer.push_back(eq2.a(i2));
m.mul(m_int_buffer.back(), b2, m_int_buffer.back());
m_var_buffer.push_back(eq2.x(i2));
i2++;
}
break;
}
if (i2 == sz2) {
// copy remaining entries from eq1
while (i1 < sz1) {
m_int_buffer.push_back(eq1.a(i1));
m.mul(m_int_buffer.back(), b1, m_int_buffer.back());
m_var_buffer.push_back(eq1.x(i1));
i1++;
}
break;
}
var x1 = eq1.x(i1);
var x2 = eq2.x(i2);
if (x1 < x2) {
m_int_buffer.push_back(eq1.a(i1));
m.mul(m_int_buffer.back(), b1, m_int_buffer.back());
m_var_buffer.push_back(eq1.x(i1));
i1++;
}
else if (x1 > x2) {
m_int_buffer.push_back(eq2.a(i2));
m.mul(m_int_buffer.back(), b2, m_int_buffer.back());
m_var_buffer.push_back(eq2.x(i2));
i2++;
}
else {
m.mul(eq1.a(i1), b1, tmp);
m.addmul(tmp, b2, eq2.a(i2), new_a);
if (!m.is_zero(new_a)) {
m_int_buffer.push_back(new_a);
m_var_buffer.push_back(eq1.x(i1));
}
i1++;
i2++;
}
}
m.del(tmp);
m.del(new_a);
SASSERT(m_int_buffer.size() == m_var_buffer.size());
if (m_int_buffer.empty())
return 0;
return mk_core(m_int_buffer.size(), m_int_buffer.c_ptr(), m_var_buffer.c_ptr());
}
void linear_equation_manager::del(linear_equation * eq) {
for (unsigned i = 0; i < eq->m_size; i++) {
m.del(eq->m_as[i]);
}
unsigned obj_sz = linear_equation::get_obj_size(eq->m_size);
m_allocator.deallocate(obj_sz, eq);
}

View file

@ -0,0 +1,85 @@
/*++
Copyright (c) 2006 Microsoft Corporation
Module Name:
linear_equation.h
Abstract:
Basic infrastructure for managing linear equations of the form:
a_1 * x_1 + ... + a_n * x_n = 0
Author:
Leonardo de Moura (leonardo) 2011-06-28
Revision History:
--*/
#ifndef _LINEAR_EQUATION_H_
#define _LINEAR_EQUATION_H_
#include"mpq.h"
#include"small_object_allocator.h"
#include"numeral_buffer.h"
#include"double_manager.h"
class linear_equation {
public:
typedef unsigned var;
private:
static unsigned get_obj_size(unsigned sz) { return sizeof(linear_equation) + sz * (sizeof(mpz) + sizeof(double) + sizeof(var)); }
friend class linear_equation_manager;
unsigned m_size;
mpz * m_as; // precise coefficients
double * m_approx_as; // approximated coefficients
var * m_xs; // var ids
linear_equation() {}
public:
unsigned size() const { return m_size; }
mpz const & a(unsigned idx) const { SASSERT(idx < m_size); return m_as[idx]; }
double approx_a(unsigned idx) const { SASSERT(idx < m_size); return m_approx_as[idx]; }
var x(unsigned idx) const { SASSERT(idx < m_size); return m_xs[idx]; }
unsigned pos(unsigned x_i) const;
void get_a(double_manager & m, unsigned idx, double & r) const { r = m_approx_as[idx]; }
template<typename NumManager>
void get_a(NumManager & m, unsigned idx, mpq & r) const { m.set(r, m_as[idx]); }
template<typename NumManager>
void get_a(NumManager & m, unsigned idx, mpz & r) const { m.set(r, m_as[idx]); }
};
class linear_equation_manager {
public:
typedef unsynch_mpq_manager numeral_manager;
typedef linear_equation::var var;
typedef numeral_buffer<mpz, numeral_manager> mpz_buffer;
private:
typedef svector<var> var_buffer;
small_object_allocator & m_allocator;
numeral_manager & m;
mpz_buffer m_int_buffer;
mpz_buffer m_val_buffer;
char_vector m_mark;
var_buffer m_var_buffer;
linear_equation * mk_core(unsigned sz, mpz * as, var * xs);
public:
linear_equation_manager(numeral_manager & _m, small_object_allocator & a):m_allocator(a), m(_m), m_int_buffer(m), m_val_buffer(m) {}
~linear_equation_manager() {}
linear_equation * mk(unsigned sz, mpq * as, var * xs, bool normalized = false);
linear_equation * mk(unsigned sz, mpz * as, var * xs, bool normalized = false);
void del(linear_equation * eq);
// Return b1 * eq1 + b2 * eq2
// return 0 if the b1 * eq1 + b2 * eq2 == 0
linear_equation * mk(mpz const & b1, linear_equation const & eq1, mpz const & b2, linear_equation const & eq2);
void display(std::ostream & out, linear_equation const & eq) const;
};
#endif

1792
src/arith_tactics/lu.cpp Normal file

File diff suppressed because it is too large Load diff

404
src/arith_tactics/lu.h Normal file
View file

@ -0,0 +1,404 @@
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
lu.h
Abstract:
Simple LU factorization module based on the paper:
"Maintaining LU factors of a General Sparse Matrix"
P. E. Gill, W. Murray, M. Saunders, M. Wright
Author:
Leonardo de Moura (leonardo) 2011-06-09
Revision History:
--*/
#ifndef _LU_H_
#define _LU_H_
#include"vector.h"
#include"mpq.h"
#include"double_manager.h"
#include"permutation.h"
#include"params.h"
#include"strategy_exception.h"
MK_ST_EXCEPTION(lu_exception);
template<typename NumManager>
class lu {
public:
typedef NumManager manager;
typedef typename NumManager::numeral numeral;
typedef svector<numeral> numeral_vector;
private:
manager & m_manager;
// Configuration
numeral m_mu; // maximum multiplier when selecting a pivot
unsigned m_selection_cutoff;
// Matrix size
unsigned m_sz; // supporting only square matrices
// Permutations
permutation P;
permutation Q;
// L
//
// It is 3 parallel vectors representing the sequence (product) of matrices
// L[0] L[1] ... L[m-1]
// where each L[i] is a tuple (A[i], indc[i], indr[i]).
// Each tuple represents a triangular factor. That is, an identity matrix
// where the position at row indc[i], and column indr[i] contains the value A[i].
// Remark: The product L[0] L[1] ... L[n-1] is not really a triangular matrix.
struct L_file {
numeral_vector A;
unsigned_vector indc;
unsigned_vector indr;
};
L_file L;
// U
//
// It is not really upper triangular, but the product PUQ is.
// The rows of U are stored in the parallel vectors (A, indr)
// Only the non-zero values are stored at U.
// The non-zeros of row i start at position begr[i] and end at
// position endr[i] of the parallel vectors (A, indr).
// The length of the row is endr[i] - begr[i].
// The coefficients are stored in A, and the column ids at indr.
//
// The factorization of a matrix A is represented as:
// L[0] L[1] ... L[m-1] P U Q
struct U_file {
numeral_vector A;
unsigned_vector indr;
unsigned_vector begr;
unsigned_vector endr;
unsigned num_entries;
U_file():num_entries(0) {}
};
U_file U;
// The actual factorization
// T_file: temporary file used for factorization
struct T_file {
// row list
unsigned_vector indr;
unsigned_vector begr;
unsigned_vector endr;
// column list
numeral_vector A;
unsigned_vector indc;
unsigned_vector begc;
unsigned_vector endc;
unsigned num_entries;
T_file():num_entries(0) {}
};
T_file T;
// Auxiliary fields
unsigned_vector locw;
// -----------------------
//
// Main
//
// -----------------------
public:
lu(manager & m, params_ref const & p);
~lu();
manager & m() const { return m_manager; }
void updt_params(params_ref const & p);
void reset();
unsigned size() const { return m_sz; }
protected:
void del_nums(numeral_vector & nums);
// -----------------------
//
// Initialization
//
// -----------------------
public:
// Contract for setting up the initial matrix:
// lu.init(size)
// - for each row r in the matrix
// - for each non-zero (a,x) in the row
// lu.add_entry(a, x)
// lu.end_row()
void init(unsigned size);
void add_entry(numeral const & a, unsigned x);
void end_row();
protected:
// auxiliary fields used during initialization
bool ini; // try if the matrix T is being setup using the protocol above
unsigned ini_irow;
unsigned fillin_for(unsigned sz);
void move_col_to_end(unsigned x);
void move_row_to_end(unsigned x);
// -----------------------
//
// Factorization
//
// -----------------------
public:
void fact();
protected:
class todo {
unsigned_vector m_elem2len;
unsigned_vector m_elem2pos;
vector<unsigned_vector> m_elems_per_len;
unsigned m_size;
public:
todo():m_size(0) {}
bool contains(unsigned elem) const { return m_elem2pos[elem] != UINT_MAX; }
void init(unsigned capacity);
void updt_len(unsigned elem, unsigned len);
unsigned len(unsigned elem) const { return m_elem2len[elem]; }
void erase(unsigned elem);
unsigned size() const { return m_size; }
void display(std::ostream & out) const;
class iterator {
todo const & m_todo;
unsigned m_i;
unsigned m_j;
unsigned m_c;
void find_next();
public:
iterator(todo const & t):m_todo(t), m_i(0), m_j(0), m_c(0) { if (!at_end()) find_next(); }
bool at_end() const { return m_c == m_todo.m_size; }
unsigned curr() const {
unsigned_vector const & v_i = m_todo.m_elems_per_len[m_i];
return v_i[m_j];
}
void next() { SASSERT(!at_end()); m_j++; m_c++; find_next(); }
};
};
todo m_todo_rows;
todo m_todo_cols;
svector<bool> m_enabled_rows;
svector<bool> m_enabled_cols;
bool enabled_row(unsigned r) const { return m_enabled_rows[r]; }
bool enabled_col(unsigned c) const { return m_enabled_cols[c]; }
unsigned_vector m_toadd_rows;
svector<bool> m_marked_rows;
// Temporary numerals
// I do not use local numerals to avoid memory leaks
numeral tol;
numeral C_max;
numeral A_ij;
numeral A_best;
numeral A_aux;
numeral tmp;
numeral mu_best;
numeral mu_1;
void init_fact();
bool stability_test(unsigned rin, unsigned cin, bool improvingM);
void select_pivot(unsigned & r_out, unsigned & c_out);
void process_pivot_core(unsigned r, unsigned c);
void process_pivot(unsigned i, unsigned r, unsigned c);
bool check_locw() const;
void dec_lenr(unsigned r);
void inc_lenr(unsigned r);
void dec_lenc(unsigned c);
void inc_lenc(unsigned c);
void del_row_entry(unsigned r, unsigned c);
void del_disabled_cols(unsigned r);
void add_row_entry(unsigned r, unsigned c);
void add_col_entry(unsigned r, unsigned c, numeral const & a);
void compress_rows();
void compress_columns();
void compress_if_needed();
void copy_T_to_U();
bool check_lenr() const;
bool check_lenc() const;
// -----------------------
//
// Solving
//
// -----------------------
public:
// Temporary vector used to interact with different solvers.
// The vector has support for tracking non-zeros.
class dense_vector {
public:
typedef typename lu<NumManager>::manager manager;
typedef typename lu<NumManager>::numeral numeral;
private:
friend class lu;
manager & m_manager;
unsigned_vector m_non_zeros; // positions that may contain non-zeros. if a position is not here, then it must contain a zero
char_vector m_in_non_zeros; // m_in_non_zeros[i] == true if m_non_zeros contains i.
numeral_vector m_values;
public:
dense_vector(manager & m, unsigned sz);
~dense_vector();
manager & m() const { return m_manager; }
void reset();
void reset(unsigned new_sz);
unsigned size() const { return m_values.size(); }
numeral const & operator[](unsigned idx) const { return m_values[idx]; }
void swap(dense_vector & other) {
m_non_zeros.swap(other.m_non_zeros);
m_in_non_zeros.swap(other.m_in_non_zeros);
m_values.swap(other.m_values);
}
// Get a given position for performing an update.
// idx is inserted into m_non_zeros.
numeral & get(unsigned idx) {
if (!m_in_non_zeros[idx]) {
m_in_non_zeros[idx] = true;
m_non_zeros.push_back(idx);
}
return m_values[idx];
}
typedef unsigned_vector::const_iterator iterator;
// iterator for positions that may contain non-zeros
iterator begin_non_zeros() const { return m_non_zeros.begin(); }
iterator end_non_zeros() const { return m_non_zeros.end(); }
void display(std::ostream & out) const;
void display_non_zeros(std::ostream & out) const;
void display_pol(std::ostream & out) const;
void elim_zeros();
};
// Solve: Lx = y
// The result is stored in y.
void solve_Lx_eq_y(dense_vector & y);
// Solve: PUQx = y
// The result is stored in y.
void solve_Ux_eq_y(dense_vector & y);
// Solve: LPUQx = y
// The result is stored in y.
void solve_Ax_eq_y(dense_vector & y) {
solve_Lx_eq_y(y);
solve_Ux_eq_y(y);
}
// Solve: xL = y
// The result is stored in y.
void solve_xL_eq_y(dense_vector & y);
// Solve: xPUQ = y
// The result is stored in y.
void solve_xU_eq_y(dense_vector & y);
// Solve: xA = y
// The result is stored in y.
void solve_xA_eq_y(dense_vector & y) {
solve_xU_eq_y(y);
solve_xL_eq_y(y);
}
private:
dense_vector m_tmp_xU_vector;
dense_vector m_tmp_replace_column_vector;
dense_vector m_tmp_vector;
dense_vector m_tmp_row;
public:
dense_vector & get_tmp_vector() { return m_tmp_vector; }
dense_vector & get_tmp_row(unsigned size) { m_tmp_row.reset(size); return m_tmp_row; }
// -----------------------
//
// Column replacement
//
// -----------------------
public:
void replace_column(unsigned j, dense_vector & new_col);
void replace_U_column(unsigned j, dense_vector & new_col);
unsigned get_num_replacements() const { return m_num_replacements; }
dense_vector & get_tmp_col() { return m_tmp_col; }
private:
unsigned m_num_replacements;
dense_vector m_tmp_col;
void del_U_row_entry(unsigned r, unsigned c);
void compress_U_rows();
void compress_U_if_needed();
void move_U_row_to_end(unsigned r);
void add_U_row_entry(unsigned r, unsigned c, numeral const & a);
void add_replace_U_row_entry(unsigned r, unsigned c, numeral const & a);
unsigned replace_U_column_core(unsigned j, dense_vector & new_col);
bool check_U_except_col(unsigned c) const;
bool check_U_except_row(unsigned r) const;
// -----------------------
//
// Invariants
//
// -----------------------
public:
bool check_P() const;
bool check_Q() const;
bool check_L() const;
bool check_U() const;
bool T_col_contains(unsigned c, unsigned r) const;
bool T_row_contains(unsigned r, unsigned c) const;
bool check_T() const;
bool check_invariant() const;
void display_T(std::ostream & out) const;
void display_U(std::ostream & out, unsigned_vector const * var_ids = 0) const;
void display_L(std::ostream & out) const;
void display(std::ostream & out, unsigned_vector const * var_ids = 0) const;
// -----------------------
//
// Info
//
// -----------------------
public:
unsigned L_size() const { return L.indc.size(); }
unsigned U_size() const { return U.num_entries; }
};
typedef lu<unsynch_mpq_manager> rational_lu;
typedef lu<double_manager> double_lu;
#endif

View file

@ -0,0 +1,135 @@
/*++
Copyright (c) 2012 Microsoft Corporation
Module Name:
mip_tactic.cpp
Abstract:
Tactic for solvig MIP (mixed integer) problem.
This is a temporary tactic. It should be deleted
after theory_arith is upgraded.
Author:
Leonardo (leonardo) 2012-02-26
Notes:
--*/
#include"tactical.h"
#include"smt_solver_exp.h"
class mip_tactic : public tactic {
struct imp;
ast_manager & m;
params_ref m_params;
statistics m_stats;
scoped_ptr<smt::solver_exp> m_solver;
void init_solver() {
smt::solver_exp * new_solver = alloc(smt::solver_exp, m, m_params);
#pragma omp critical (tactic_cancel)
{
m_solver = new_solver;
}
}
public:
mip_tactic(ast_manager & _m, params_ref const & p):
m(_m),
m_params(p) {
}
virtual tactic * translate(ast_manager & m) {
return alloc(mip_tactic, m, m_params);
}
virtual ~mip_tactic() {}
virtual void updt_params(params_ref const & p) {
m_params = p;
}
virtual void collect_param_descrs(param_descrs & r) {
}
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());
bool produce_models = g->models_enabled();
mc = 0; pc = 0; core = 0; result.reset();
tactic_report report("mip", *g);
fail_if_proof_generation("mip", g);
fail_if_unsat_core_generation("mip", g);
g->elim_redundancies();
if (g->inconsistent()) {
result.push_back(g.get());
return;
}
init_solver();
m_solver->assert_goal(*g);
lbool r;
try {
r = m_solver->check();
}
catch (strategy_exception & ex) {
// solver_exp uses assertion_sets and strategy_exception's
throw tactic_exception(ex.msg());
}
m_solver->collect_statistics(m_stats);
if (r == l_false) {
g->reset();
g->assert_expr(m.mk_false());
}
else if (r == l_true) {
g->reset();
if (produce_models) {
model_ref md;
m_solver->get_model(md);
mc = model2model_converter(md.get());
}
}
else {
// failed
}
g->inc_depth();
result.push_back(g.get());
TRACE("mip", g->display(tout););
SASSERT(g->is_well_sorted());
}
virtual void cleanup() {
if (m_solver)
m_solver->collect_statistics(m_stats);
#pragma omp critical (tactic_cancel)
{
m_solver = 0;
}
}
virtual void collect_statistics(statistics & st) const {
st.copy(m_stats);
}
virtual void reset_statistics() {
m_stats.reset();
}
virtual void set_cancel(bool f) {
if (m_solver)
m_solver->set_cancel(f);
}
};
tactic * mk_mip_tactic(ast_manager & m, params_ref const & p) {
return clean(alloc(mip_tactic, m, p));
}

View file

@ -0,0 +1,30 @@
/*++
Copyright (c) 2012 Microsoft Corporation
Module Name:
mip_tactic.h
Abstract:
Tactic for solvig MIP (mixed integer) problem.
This is a temporary tactic. It should be deleted
after theory_arith is upgraded.
Author:
Leonardo (leonardo) 2012-02-26
Notes:
--*/
#ifndef _MIP_TACTIC_H_
#define _MIP_TACTIC_H_
#include"params.h"
class ast_manager;
class tactic;
tactic * mk_mip_tactic(ast_manager & m, params_ref const & p = params_ref());
#endif

View file

@ -0,0 +1,480 @@
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
nla2bv_tactic.cpp
Abstract:
Convert quantified NIA problems to bounded bit-vector arithmetic problems.
Author:
Nikolaj (nbjorner) 2011-05-3
Notes:
Ported to tactic framework on 2012-02-28
The original file was called qfnla2bv.cpp
--*/
#include "tactical.h"
#include "arith_decl_plugin.h"
#include "bv_decl_plugin.h"
#include "for_each_expr.h"
#include "expr_replacer.h"
#include "optional.h"
#include "bv2int_rewriter.h"
#include "bv2real_rewriter.h"
#include "extension_model_converter.h"
#include "filter_model_converter.h"
#include "bound_manager.h"
#include "obj_pair_hashtable.h"
#include "ast_smt2_pp.h"
//
//
// 1. for each variable, determine bounds (s.t., non-negative variables
// have unsigned bit-vectors).
//
// 2. replace uninterpreted variables of sort int by
// expressions of the form +- bv2int(b) +- k
// where k is a slack.
//
// 3. simplify resulting assertion set to reduce occurrences of bv2int.
//
class nla2bv_tactic : public tactic {
class imp {
typedef rational numeral;
ast_manager & m_manager;
bool m_is_sat_preserving;
arith_util m_arith;
bv_util m_bv;
bv2real_util m_bv2real;
bv2int_rewriter_ctx m_bv2int_ctx;
bound_manager m_bounds;
expr_substitution m_subst;
func_decl_ref_vector m_vars;
expr_ref_vector m_defs;
expr_ref_vector m_trail;
unsigned m_num_bits;
unsigned m_default_bv_size;
ref<filter_model_converter> m_fmc;
public:
imp(ast_manager & m, params_ref const& p):
m_manager(m),
m_is_sat_preserving(true),
m_arith(m),
m_bv(m),
m_bv2real(m, rational(p.get_uint(":nla2bv-root",2)), rational(p.get_uint(":nla2bv-divisor",2)), p.get_uint(":nla2bv-max-bv-size", UINT_MAX)),
m_bv2int_ctx(m, p),
m_bounds(m),
m_subst(m),
m_vars(m),
m_defs(m),
m_trail(m),
m_fmc(0) {
m_default_bv_size = m_num_bits = p.get_uint(":nla2bv-bv-size", 4);
}
~imp() {}
void operator()(goal & g, model_converter_ref & mc) {
TRACE("nla2bv", g.display(tout);
tout << "Muls: " << count_mul(g) << "\n";
);
m_fmc = alloc(filter_model_converter, m_manager);
m_bounds(g);
collect_power2(g);
if(!collect_vars(g)) {
throw tactic_exception("goal is not in the fragment supported by nla2bv");
}
tactic_report report("nla->bv", g);
substitute_vars(g);
TRACE("nla2bv", g.display(tout << "substitute vars\n"););
reduce_bv2int(g);
reduce_bv2real(g);
TRACE("nla2bv", g.display(tout << "after reduce\n"););
extension_model_converter * evc = alloc(extension_model_converter, m_manager);
mc = concat(m_fmc.get(), evc);
for (unsigned i = 0; i < m_vars.size(); ++i) {
evc->insert(m_vars[i].get(), m_defs[i].get());
}
for (unsigned i = 0; i < m_bv2real.num_aux_decls(); ++i) {
m_fmc->insert(m_bv2real.get_aux_decl(i));
}
IF_VERBOSE(TACTIC_VERBOSITY_LVL, verbose_stream() << "(nla->bv :sat-preserving " << m_is_sat_preserving << ")\n";);
TRACE("nla2bv_verbose", g.display(tout););
TRACE("nla2bv", tout << "Muls: " << count_mul(g) << "\n";);
g.inc_depth();
if (!is_sat_preserving())
g.updt_prec(goal::UNDER);
}
bool const& is_sat_preserving() const { return m_is_sat_preserving; }
private:
void set_satisfiability_preserving(bool f) {
m_is_sat_preserving = f;
}
void collect_power2(goal & g) {
m_bv2int_ctx.collect_power2(g);
obj_map<expr, expr*> const& p2 = m_bv2int_ctx.power2();
if (p2.empty()) return;
obj_map<expr, expr*>::iterator it = p2.begin(), end = p2.end();
for (; it != end; ++it) {
expr* v = it->m_value;
unsigned num_bits = m_bv.get_bv_size(v);
expr* w = m_bv.mk_bv2int(m_bv.mk_bv_shl(m_bv.mk_numeral(1, num_bits), v));
m_trail.push_back(w);
m_subst.insert(it->m_key, w);
TRACE("nla2bv", tout << mk_ismt2_pp(it->m_key, m_manager) << " " << mk_ismt2_pp(w, m_manager) << "\n";);
}
// eliminate the variables that are power of two.
substitute_vars(g);
m_subst.reset();
}
// eliminate bv2int from formula
void reduce_bv2int(goal & g) {
bv2int_rewriter_star reduce(m_manager, m_bv2int_ctx);
expr_ref r(m_manager);
for (unsigned i = 0; i < g.size(); ++i) {
reduce(g.form(i), r);
g.update(i, r);
}
assert_side_conditions(g, m_bv2int_ctx.num_side_conditions(),
m_bv2int_ctx.side_conditions());
}
// eliminate bv2real from formula
void reduce_bv2real(goal & g) {
bv2real_rewriter_star reduce(m_manager, m_bv2real);
expr_ref r(m_manager);
for (unsigned i = 0; i < g.size(); ++i) {
reduce(g.form(i), r);
if (m_bv2real.contains_bv2real(r)) {
throw tactic_exception("nla2bv could not eliminate reals");
}
g.update(i, r);
}
assert_side_conditions(g, m_bv2real.num_side_conditions(),
m_bv2real.side_conditions());
}
void assert_side_conditions(goal & g, unsigned sz, expr * const * conditions) {
for (unsigned i = 0; i < sz; ++i) {
g.assert_expr(conditions[i]);
set_satisfiability_preserving(false);
}
TRACE("nla2bv",
for (unsigned i = 0; i < sz; ++i) {
tout << mk_ismt2_pp(conditions[i], m_manager) << "\n";
});
}
// substitute variables by bit-vectors
void substitute_vars(goal & g) {
scoped_ptr<expr_replacer> er = mk_default_expr_replacer(m_manager);
er->set_substitution(&m_subst);
expr_ref r(m_manager);
for (unsigned i = 0; i < g.size(); ++i) {
(*er)(g.form(i), r);
g.update(i, r);
}
}
// -----------------
// collect uninterpreted variables in problem.
// create a substitution from the variables to
// bit-vector terms.
//
void add_var(app* n) {
if (m_arith.is_int(n)) {
add_int_var(n);
}
else {
SASSERT(m_arith.is_real(n));
add_real_var(n);
}
}
void add_int_var(app* n) {
expr_ref s_bv(m_manager);
sort_ref bv_sort(m_manager);
optional<numeral> low, up;
numeral tmp;
bool is_strict;
if (m_bounds.has_lower(n, tmp, is_strict)) {
SASSERT(!is_strict);
low = tmp;
}
if (m_bounds.has_upper(n, tmp, is_strict)) {
SASSERT(!is_strict);
up = tmp;
}
//
// [low .. up]
// num_bits = log2(1 + |up - low|) or m_num_bits
//
unsigned num_bits = m_num_bits;
if (up && low) {
num_bits = log2(abs(*up - *low)+numeral(1));
}
else {
TRACE("nla2bv", tout << "no bounds for " << mk_ismt2_pp(n, m_manager) << "\n";);
set_satisfiability_preserving(false);
}
bv_sort = m_bv.mk_sort(num_bits);
std::string name = n->get_decl()->get_name().str();
s_bv = m_manager.mk_fresh_const(name.c_str(), bv_sort);
m_fmc->insert(to_app(s_bv)->get_decl());
s_bv = m_bv.mk_bv2int(s_bv);
if (low) {
if (!(*low).is_zero()) {
// low <= s_bv
// ~>
// replace s_bv by s_bv + low
// add 'low' to model for n.
//
s_bv = m_arith.mk_add(s_bv, m_arith.mk_numeral(*low, true));
}
}
else if (up) {
// s_bv <= up
// ~>
// replace s_bv by up - s_bv
//
s_bv = m_arith.mk_sub(m_arith.mk_numeral(*up, true), s_bv);
}
else {
s_bv = m_arith.mk_sub(s_bv, m_arith.mk_numeral(m_bv.power_of_two(num_bits-1), true));
}
m_trail.push_back(s_bv);
m_subst.insert(n, s_bv);
m_vars.push_back(n->get_decl());
m_defs.push_back(s_bv);
}
void add_real_var(app* n) {
expr_ref s_bv(m_manager), s_bvr(m_manager), s(m_manager), t(m_manager);
sort_ref bv_sort(m_manager);
bv_sort = m_bv.mk_sort(m_num_bits);
set_satisfiability_preserving(false);
std::string name = n->get_decl()->get_name().str();
s = m_manager.mk_fresh_const(name.c_str(), bv_sort);
name += "_r";
t = m_manager.mk_fresh_const(name.c_str(), bv_sort);
m_fmc->insert(to_app(s)->get_decl());
m_fmc->insert(to_app(t)->get_decl());
s_bv = m_bv2real.mk_bv2real(s, t);
m_trail.push_back(s_bv);
m_subst.insert(n, s_bv);
m_vars.push_back(n->get_decl());
// use version without bv2real function.
m_bv2real.mk_bv2real_reduced(s, t, s_bvr);
m_defs.push_back(s_bvr);
}
// update number of bits based on the largest constant used.
void update_num_bits(app* n) {
bool is_int;
numeral nm;
if (m_arith.is_numeral(n, nm, is_int) && is_int) {
nm = abs(nm);
unsigned l = log2(nm);
if (m_num_bits <= l) {
m_num_bits = l+1;
}
}
}
unsigned log2(rational const& n) {
rational pow(1), two(2);
unsigned sz = 0;
while (pow < n) {
++sz;
pow *= two;
}
if (sz == 0) sz = 1;
return sz;
}
class get_uninterp_proc {
imp& m_imp;
ptr_vector<app> m_vars;
bool m_in_supported_fragment;
public:
get_uninterp_proc(imp& s): m_imp(s), m_in_supported_fragment(true) {}
ptr_vector<app> const& vars() { return m_vars; }
void operator()(var * n) {
m_in_supported_fragment = false;
}
void operator()(app* n) {
arith_util& a = m_imp.m_arith;
ast_manager& m = a.get_manager();
if (a.is_int(n) &&
is_uninterp_const(n)) {
m_vars.push_back(n);
}
else if (a.is_real(n) &&
is_uninterp_const(n)) {
m_vars.push_back(n);
}
else if (m.is_bool(n) && is_uninterp_const(n)) {
}
else if (!(a.is_mul(n) ||
a.is_add(n) ||
a.is_sub(n) ||
a.is_le(n) ||
a.is_lt(n) ||
a.is_ge(n) ||
a.is_gt(n) ||
a.is_numeral(n) ||
a.is_uminus(n) ||
m_imp.m_bv2real.is_pos_le(n) ||
m_imp.m_bv2real.is_pos_lt(n) ||
n->get_family_id() == a.get_manager().get_basic_family_id())) {
TRACE("nla2bv", tout << "Not supported: " << mk_ismt2_pp(n, a.get_manager()) << "\n";);
m_in_supported_fragment = false;
}
m_imp.update_num_bits(n);
}
void operator()(quantifier* q) {
m_in_supported_fragment = false;
}
bool is_supported() const { return m_in_supported_fragment; }
};
bool collect_vars(goal const & g) {
get_uninterp_proc fe_var(*this);
for_each_expr_at(fe_var, g);
for (unsigned i = 0; i < fe_var.vars().size(); ++i) {
add_var(fe_var.vars()[i]);
}
return fe_var.is_supported() && !fe_var.vars().empty();
}
class count_mul_proc {
imp& m_imp;
unsigned m_count;
public:
count_mul_proc(imp& s): m_imp(s), m_count(0) {}
unsigned count() const { return m_count; }
void operator()(var * n) {}
void operator()(app* n) {
if (m_imp.m_arith.is_mul(n)) {
m_count += n->get_num_args()-1;
}
if (m_imp.m_bv.is_bv_mul(n)) {
unsigned num_vars = 0;
for (unsigned j = 0; j < n->get_num_args(); ++j) {
if (!m_imp.m_bv.is_numeral(n->get_arg(j))) {
++num_vars;
}
}
if (num_vars > 1) {
m_count += num_vars - 1;
}
}
}
void operator()(quantifier* q) {}
};
unsigned count_mul(goal const & g) {
count_mul_proc c(*this);
for_each_expr_at(c, g);
return c.count();
}
};
params_ref m_params;
imp * m_imp;
struct scoped_set_imp {
nla2bv_tactic & m_owner;
scoped_set_imp(nla2bv_tactic & o, imp & i):
m_owner(o) {
#pragma omp critical (tactic_cancel)
{
m_owner.m_imp = &i;
}
}
~scoped_set_imp() {
#pragma omp critical (tactic_cancel)
{
m_owner.m_imp = 0;
}
}
};
public:
nla2bv_tactic(params_ref const & p):
m_params(p),
m_imp(0) {
}
virtual tactic * translate(ast_manager & m) {
return alloc(nla2bv_tactic, m_params);
}
virtual ~nla2bv_tactic() {
}
virtual void updt_params(params_ref const & p) {
m_params = p;
}
virtual void collect_param_descrs(param_descrs & r) {
r.insert(":nla2bv-max-bv-size", CPK_UINT, "(default: inf) maximum bit-vector size used by nla2bv tactic");
r.insert(":nla2bv-bv-size", CPK_UINT, "(default: 4) default bit-vector size used by nla2bv tactic.");
r.insert(":nla2bv-root", CPK_UINT, "(default: 2) nla2bv tactic encodes reals into bit-vectors using expressions of the form a+b*sqrt(c), this parameter sets the value of c used in the encoding.");
r.insert(":nla2bv-divisor", CPK_UINT, "(default: 2) nla2bv tactic parameter.");
}
/**
\brief Modify a goal to use bounded bit-vector
arithmetic in place of non-linear integer arithmetic.
\return false if transformation is not possible.
*/
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());
fail_if_proof_generation("nla2bv", g);
fail_if_unsat_core_generation("nla2bv", g);
mc = 0; pc = 0; core = 0; result.reset();
imp proc(g->m(), m_params);
scoped_set_imp setter(*this, proc);
proc(*(g.get()), mc);
result.push_back(g.get());
SASSERT(g->is_well_sorted());
}
virtual void cleanup(void) {
}
};
tactic * mk_nla2bv_tactic(ast_manager & m, params_ref const & p) {
return alloc(nla2bv_tactic, p);
}

View file

@ -0,0 +1,30 @@
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
nla2bv_tactic.cpp
Abstract:
Convert quantified NIA problems to bounded bit-vector arithmetic problems.
Author:
Nikolaj (nbjorner) 2011-05-3
Notes:
Ported to tactic framework on 2012-02-28
--*/
#ifndef _NLA2BV_TACTIC_H_
#define _NLA2BV_TACTIC_H_
#include"params.h"
class ast_manager;
class tactic;
tactic * mk_nla2bv_tactic(ast_manager & m, params_ref const & p = params_ref());
#endif

View file

@ -0,0 +1,211 @@
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
normalize_bounds_tactic.cpp
Abstract:
Replace x with x' + l, when l <= x
where x' is a fresh variable.
Note that, after the transformation 0 <= x'.
Author:
Leonardo de Moura (leonardo) 2011-10-21.
Revision History:
--*/
#include"tactical.h"
#include"bound_manager.h"
#include"th_rewriter.h"
#include"extension_model_converter.h"
#include"filter_model_converter.h"
#include"arith_decl_plugin.h"
#include"expr_substitution.h"
#include"ast_smt2_pp.h"
class normalize_bounds_tactic : public tactic {
struct imp {
ast_manager & m;
bound_manager m_bm;
arith_util m_util;
th_rewriter m_rw;
bool m_normalize_int_only;
imp(ast_manager & _m, params_ref const & p):
m(_m),
m_bm(m),
m_util(m),
m_rw(m, p) {
updt_params(p);
}
void updt_params_core(params_ref const & p) {
m_normalize_int_only = p.get_bool(":norm-int-only", true);
}
void updt_params(params_ref const & p) {
m_rw.updt_params(p);
updt_params_core(p);
}
void set_cancel(bool f) {
m_rw.set_cancel(f);
}
bool is_target(expr * var, rational & val) {
bool strict;
return
is_uninterp_const(var) &&
(!m_normalize_int_only || m_util.is_int(var)) &&
m_bm.has_lower(var, val, strict) &&
!val.is_zero();
}
bool is_target(expr * var) {
rational val;
return is_target(var, val);
}
bool has_lowers() {
bound_manager::iterator it = m_bm.begin();
bound_manager::iterator end = m_bm.end();
for (; it != end; ++it) {
TRACE("normalize_bounds_tactic",
rational val; bool strict;
tout << mk_ismt2_pp(*it, m) << " has_lower: " << m_bm.has_lower(*it, val, strict) << " val: " << val << "\n";);
if (is_target(*it))
return true;
}
return false;
}
virtual void operator()(goal_ref const & in,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
mc = 0; pc = 0; core = 0;
bool produce_models = in->models_enabled();
bool produce_proofs = in->proofs_enabled();
tactic_report report("normalize-bounds", *in);
m_bm(*in);
if (!has_lowers()) {
result.push_back(in.get());
// did not increase depth since it didn't do anything.
return;
}
extension_model_converter * mc1 = 0;
filter_model_converter * mc2 = 0;
if (produce_models) {
mc1 = alloc(extension_model_converter, m);
mc2 = alloc(filter_model_converter, m);
mc = concat(mc2, mc1);
}
unsigned num_norm_bounds = 0;
expr_substitution subst(m);
rational val;
bound_manager::iterator it = m_bm.begin();
bound_manager::iterator end = m_bm.end();
for (; it != end; ++it) {
expr * x = *it;
if (is_target(x, val)) {
num_norm_bounds++;
sort * s = m.get_sort(x);
app * x_prime = m.mk_fresh_const(0, s);
expr * def = m_util.mk_add(x_prime, m_util.mk_numeral(val, s));
subst.insert(x, def);
if (produce_models) {
mc1->insert(to_app(x)->get_decl(), def);
mc2->insert(x_prime->get_decl());
}
}
}
report_tactic_progress(":normalized-bounds", num_norm_bounds);
m_rw.set_substitution(&subst);
expr_ref new_curr(m);
proof_ref new_pr(m);
unsigned size = in->size();
for (unsigned idx = 0; idx < size; idx++) {
expr * curr = in->form(idx);
m_rw(curr, new_curr, new_pr);
if (produce_proofs) {
proof * pr = in->pr(idx);
new_pr = m.mk_modus_ponens(pr, new_pr);
}
in->update(idx, new_curr, new_pr, in->dep(idx));
}
TRACE("normalize_bounds_tactic", in->display(tout););
in->inc_depth();
result.push_back(in.get());
}
};
imp * m_imp;
params_ref m_params;
public:
normalize_bounds_tactic(ast_manager & m, params_ref const & p):
m_params(p) {
m_imp = alloc(imp, m, p);
}
virtual tactic * translate(ast_manager & m) {
return alloc(normalize_bounds_tactic, m, m_params);
}
virtual ~normalize_bounds_tactic() {
dealloc(m_imp);
}
virtual void updt_params(params_ref const & p) {
m_imp->updt_params(p);
}
virtual void collect_param_descrs(param_descrs & r) {
insert_produce_models(r);
r.insert(":norm-int-only", CPK_BOOL, "(default: true) normalize only the bounds of integer constants.");
}
virtual void operator()(goal_ref const & in,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
(*m_imp)(in, result, mc, pc, core);
}
virtual void cleanup() {
ast_manager & m = m_imp->m;
imp * d = m_imp;
#pragma omp critical (tactic_cancel)
{
d = m_imp;
}
dealloc(d);
d = alloc(imp, m, m_params);
#pragma omp critical (tactic_cancel)
{
m_imp = d;
}
}
protected:
virtual void set_cancel(bool f) {
if (m_imp)
m_imp->set_cancel(f);
}
};
tactic * mk_normalize_bounds_tactic(ast_manager & m, params_ref const & p) {
return clean(alloc(normalize_bounds_tactic, m, p));
}

View file

@ -0,0 +1,30 @@
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
normalize_bounds_tactic.h
Abstract:
Replace x with x' + l, when l <= x
where x' is a fresh variable.
Note that, after the transformation 0 <= x'.
Author:
Leonardo de Moura (leonardo) 2011-10-21.
Revision History:
--*/
#ifndef _NORMALIZE_BOUNDS_TACTIC_H_
#define _NORMALIZE_BOUNDS_TACTIC_H_
#include"params.h"
class ast_manager;
class tactic;
tactic * mk_normalize_bounds_tactic(ast_manager & m, params_ref const & p = params_ref());
#endif

View file

@ -0,0 +1,102 @@
/*++
Copyright (c) 2012 Microsoft Corporation
Module Name:
pb2bv_model_converter.cpp
Abstract:
Model converter for the pb2bv tactic.
Author:
Christoph (cwinter) 2012-02-15
Notes:
--*/
#include"trace.h"
#include"arith_decl_plugin.h"
#include"model_v2_pp.h"
#include"pb2bv_model_converter.h"
pb2bv_model_converter::pb2bv_model_converter(ast_manager & _m, obj_map<func_decl, expr*> const & c2bit, bound_manager const & bm):
m(_m) {
obj_map<func_decl, expr*>::iterator it = c2bit.begin();
obj_map<func_decl, expr*>::iterator end = c2bit.end();
for ( ; it != end; it++) {
m_c2bit.push_back(func_decl_pair(it->m_key, to_app(it->m_value)->get_decl()));
m.inc_ref(it->m_key);
m.inc_ref(to_app(it->m_value)->get_decl());
}
bound_manager::iterator it2 = bm.begin();
bound_manager::iterator end2 = bm.end();
for (; it2 != end2; ++it2) {
expr * c = *it2;
SASSERT(is_uninterp_const(c));
func_decl * d = to_app(c)->get_decl();
if (!c2bit.contains(d)) {
SASSERT(d->get_arity() == 0);
m.inc_ref(d);
m_c2bit.push_back(func_decl_pair(d, static_cast<func_decl*>(0)));
}
}
}
pb2bv_model_converter::~pb2bv_model_converter() {
svector<func_decl_pair>::const_iterator it = m_c2bit.begin();
svector<func_decl_pair>::const_iterator end = m_c2bit.end();
for (; it != end; ++it) {
m.dec_ref(it->first);
m.dec_ref(it->second);
}
}
void pb2bv_model_converter::operator()(model_ref & md) {
(*this)(md, 0);
}
void pb2bv_model_converter::operator()(model_ref & md, unsigned goal_idx) {
SASSERT(goal_idx == 0);
TRACE("pb2bv", tout << "converting model:\n"; model_v2_pp(tout, *md); display(tout););
arith_util a_util(m);
svector<func_decl_pair>::const_iterator it = m_c2bit.begin();
svector<func_decl_pair>::const_iterator end = m_c2bit.end();
for (; it != end; ++it) {
if (it->second) {
expr * val = md->get_const_interp(it->second);
if (val == 0 || m.is_false(val)) {
/* false's and don't cares get the integer 0 solution*/
md->register_decl(it->first, a_util.mk_numeral(rational(0), true));
}
else {
md->register_decl(it->first, a_util.mk_numeral(rational(1), true));
}
}
else {
// it->first is a don't care.
md->register_decl(it->first, a_util.mk_numeral(rational(0), true));
}
}
}
void pb2bv_model_converter::display(std::ostream & out) {
out << "(pb2bv-model-converter";
svector<func_decl_pair>::const_iterator it = m_c2bit.begin();
svector<func_decl_pair>::const_iterator end = m_c2bit.end();
for (; it != end; ++it) {
out << "\n (" << it->first->get_name() << " ";
if (it->second == 0)
out << "0";
else
out << it->second->get_name();
out << ")";
}
out << ")\n";
}
model_converter * pb2bv_model_converter::translate(ast_translation & translator) {
NOT_IMPLEMENTED_YET();
}

View file

@ -0,0 +1,39 @@
/*++
Copyright (c) 2012 Microsoft Corporation
Module Name:
pb2bv_model_converter.h
Abstract:
Model converter for the pb2bv tactic.
Author:
Christoph (cwinter) 2012-02-15
Notes:
--*/
#ifndef _PB2BV_MODEL_CONVERTER_
#define _PB2BV_MODEL_CONVERTER_
#include"model_converter.h"
#include"bound_manager.h"
class pb2bv_model_converter : public model_converter {
typedef std::pair<func_decl *, func_decl *> func_decl_pair;
ast_manager & m;
svector<func_decl_pair> m_c2bit;
public:
pb2bv_model_converter(ast_manager & _m, obj_map<func_decl, expr*> const & c2bit, bound_manager const & bm);
virtual ~pb2bv_model_converter();
virtual void operator()(model_ref & md);
virtual void operator()(model_ref & md, unsigned goal_idx);
virtual void display(std::ostream & out);
virtual model_converter * translate(ast_translation & translator);
};
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,30 @@
/*++
Copyright (c) 2012 Microsoft Corporation
Module Name:
pb2bv_tactic.cpp
Abstract:
Tactic for converting Pseudo-Boolean constraints to BV
Author:
Christoph (cwinter) 2012-02-15
Notes:
--*/
#ifndef _PB2BV_TACTIC_
#define _PB2BV_TACTIC_
#include"params.h"
class ast_manager;
class tactic;
tactic * mk_pb2bv_tactic(ast_manager & m, params_ref const & p = params_ref());
probe * mk_is_pb_probe();
#endif

View file

@ -0,0 +1,421 @@
/*++
Copyright (c) 2012 Microsoft Corporation
Module Name:
probe_arith.cpp
Abstract:
Some probes for arithmetic problems.
Author:
Leonardo de Moura (leonardo) 2012-03-01.
Revision History:
--*/
#include"probe.h"
#include"expr2polynomial.h"
#include"for_each_expr.h"
#include"arith_decl_plugin.h"
#include"goal_util.h"
class arith_degree_probe : public probe {
struct proc {
ast_manager & m;
unsynch_mpq_manager m_qm;
polynomial::manager m_pm;
default_expr2polynomial m_expr2poly;
arith_util m_util;
unsigned m_max_degree;
unsigned long long m_acc_degree;
unsigned m_counter;
proc(ast_manager & _m):m(_m), m_pm(m_qm), m_expr2poly(m, m_pm), m_util(m) {
m_max_degree = 0;
m_acc_degree = 0;
m_counter = 0;
}
void updt_degree(polynomial_ref const & p) {
unsigned deg = m_pm.total_degree(p);
if (deg > m_max_degree)
m_max_degree = deg;
m_acc_degree += deg;
m_counter++;
}
void process(app * n) {
expr * lhs = n->get_arg(0);
expr * rhs = n->get_arg(1);
polynomial_ref p1(m_pm);
polynomial_ref p2(m_pm);
scoped_mpz d1(m_qm);
scoped_mpz d2(m_qm);
m_expr2poly.to_polynomial(lhs, p1, d1);
m_expr2poly.to_polynomial(rhs, p2, d2);
updt_degree(p1);
updt_degree(p2);
}
void operator()(var * n) {}
void operator()(quantifier * n) {}
void operator()(app * n) {
if (m_util.is_le(n) || m_util.is_lt(n) || m_util.is_gt(n) || m_util.is_ge(n))
process(n);
if (m.is_eq(n) && m_util.is_int_real(n->get_arg(0)))
process(n);
}
};
bool m_avg;
public:
arith_degree_probe(bool avg):m_avg(avg) {}
virtual result operator()(goal const & g) {
proc p(g.m());
for_each_expr_at(p, g);
if (m_avg)
return p.m_counter == 0 ? 0.0 : static_cast<double>(p.m_acc_degree)/static_cast<double>(p.m_counter);
else
return p.m_max_degree;
}
};
class arith_bw_probe : public probe {
struct proc {
ast_manager & m;
arith_util m_util;
unsigned m_max_bw;
unsigned long long m_acc_bw;
unsigned m_counter;
proc(ast_manager & _m):m(_m), m_util(m) {
m_max_bw = 0;
m_acc_bw = 0;
m_counter = 0;
}
void operator()(var * n) {}
void operator()(quantifier * n) {}
void operator()(app * n) {
rational val;
if (m_util.is_numeral(n, val)) {
unsigned bw = val.bitsize();
if (bw > m_max_bw)
m_max_bw = bw;
m_acc_bw += bw;
m_counter++;
}
}
};
bool m_avg;
public:
arith_bw_probe(bool avg):m_avg(avg) {}
virtual result operator()(goal const & g) {
proc p(g.m());
for_each_expr_at(p, g);
if (m_avg)
return p.m_counter == 0 ? 0.0 : static_cast<double>(p.m_acc_bw)/static_cast<double>(p.m_counter);
else
return p.m_max_bw;
}
};
probe * mk_arith_avg_degree_probe() {
return alloc(arith_degree_probe, true);
}
probe * mk_arith_max_degree_probe() {
return alloc(arith_degree_probe, false);
}
probe * mk_arith_avg_bw_probe() {
return alloc(arith_bw_probe, true);
}
probe * mk_arith_max_bw_probe() {
return alloc(arith_bw_probe, false);
}
struct is_non_qflira_functor {
struct found {};
ast_manager & m;
arith_util u;
bool m_int;
bool m_real;
is_non_qflira_functor(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();
}
};
static bool is_qflia(goal const & g) {
is_non_qflira_functor p(g.m(), true, false);
return !test(g, p);
}
class is_qflia_probe : public probe {
public:
virtual result operator()(goal const & g) {
return is_qflia(g);
}
};
static bool is_qflra(goal const & g) {
is_non_qflira_functor p(g.m(), false, true);
return !test(g, p);
}
class is_qflra_probe : public probe {
public:
virtual result operator()(goal const & g) {
return is_qflra(g);
}
};
static bool is_qflira(goal const & g) {
is_non_qflira_functor p(g.m(), true, true);
return !test(g, p);
}
class is_qflira_probe : public probe {
public:
virtual result operator()(goal const & g) {
return is_qflira(g);
}
};
static bool is_lp(goal const & g) {
ast_manager & m = g.m();
arith_util u(m);
unsigned sz = g.size();
for (unsigned i = 0; i < sz; i++) {
expr * f = g.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;
}
static bool is_ilp(goal const & g) {
if (!is_qflia(g))
return false;
if (has_term_ite(g))
return false;
return is_lp(g);
}
static bool is_mip(goal const & g) {
if (!is_qflira(g))
return false;
if (has_term_ite(g))
return false;
return is_lp(g);
}
class is_ilp_probe : public probe {
public:
virtual result operator()(goal const & g) {
return is_ilp(g);
}
};
class is_mip_probe : public probe {
public:
virtual result operator()(goal const & g) {
return is_mip(g);
}
};
probe * mk_is_qflia_probe() {
return alloc(is_qflia_probe);
}
probe * mk_is_qflra_probe() {
return alloc(is_qflra_probe);
}
probe * mk_is_qflira_probe() {
return alloc(is_qflira_probe);
}
probe * mk_is_ilp_probe() {
return alloc(is_ilp_probe);
}
probe * mk_is_mip_probe() {
return alloc(is_mip_probe);
}
struct is_non_nira_functor {
struct found {};
ast_manager & m;
arith_util u;
bool m_int;
bool m_real;
bool m_quant;
is_non_nira_functor(ast_manager & _m, bool _int, bool _real, bool _quant):m(_m), u(m), m_int(_int), m_real(_real), m_quant(_quant) {}
void operator()(var * x) {
if (!m_quant)
throw found();
sort * s = x->get_sort();
if (m_int && u.is_int(s))
return;
if (m_real && u.is_real(s))
return;
throw found();
}
void operator()(quantifier *) {
if (!m_quant)
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())
return;
if (is_uninterp_const(n))
return;
throw found();
}
};
static bool is_qfnia(goal const & g) {
is_non_nira_functor p(g.m(), true, false, false);
return !test(g, p);
}
static bool is_qfnra(goal const & g) {
is_non_nira_functor p(g.m(), false, true, false);
return !test(g, p);
}
static bool is_nia(goal const & g) {
is_non_nira_functor p(g.m(), true, false, true);
return !test(g, p);
}
static bool is_nra(goal const & g) {
is_non_nira_functor p(g.m(), false, true, true);
return !test(g, p);
}
class is_qfnia_probe : public probe {
public:
virtual result operator()(goal const & g) {
return is_qfnia(g);
}
};
class is_qfnra_probe : public probe {
public:
virtual result operator()(goal const & g) {
return is_qfnra(g);
}
};
class is_nia_probe : public probe {
public:
virtual result operator()(goal const & g) {
return is_nia(g);
}
};
class is_nra_probe : public probe {
public:
virtual result operator()(goal const & g) {
return is_nra(g);
}
};
probe * mk_is_qfnia_probe() {
return alloc(is_qfnia_probe);
}
probe * mk_is_qfnra_probe() {
return alloc(is_qfnra_probe);
}
probe * mk_is_nia_probe() {
return alloc(is_nia_probe);
}
probe * mk_is_nra_probe() {
return alloc(is_nra_probe);
}

View file

@ -0,0 +1,39 @@
/*++
Copyright (c) 2012 Microsoft Corporation
Module Name:
probe_arith.h
Abstract:
Some probes for arithmetic problems.
Author:
Leonardo de Moura (leonardo) 2012-03-01.
Revision History:
--*/
#ifndef _PROBE_ARITH_H_
#define _PROBE_ARITH_H_
class probe;
probe * mk_arith_avg_bw_probe();
probe * mk_arith_max_bw_probe();
probe * mk_arith_avg_degree_probe();
probe * mk_arith_max_degree_probe();
probe * mk_is_qflia_probe();
probe * mk_is_qflra_probe();
probe * mk_is_qflira_probe();
probe * mk_is_ilp_probe();
probe * mk_is_mip_probe();
probe * mk_is_qfnia_probe();
probe * mk_is_qfnra_probe();
probe * mk_is_nia_probe();
probe * mk_is_nra_probe();
#endif

View file

@ -0,0 +1,563 @@
/*++
Copyright (c) 2012 Microsoft Corporation
Module Name:
propagate_ineqs_tactic.h
Abstract:
This tactic performs the following tasks:
- Propagate bounds using the bound_propagator.
- Eliminate subsumed inequalities.
For example:
x - y >= 3
can be replaced with true if we know that
x >= 3 and y <= 0
- Convert inequalities of the form p <= k and p >= k into p = k,
where p is a polynomial and k is a constant.
This strategy assumes the input is in arith LHS mode.
This can be achieved by using option :arith-lhs true in the
simplifier.
Author:
Leonardo (leonardo) 2012-02-19
Notes:
--*/
#include"tactical.h"
#include"bound_propagator.h"
#include"arith_decl_plugin.h"
#include"simplify_tactic.h"
#include"ast_smt2_pp.h"
class propagate_ineqs_tactic : public tactic {
struct imp;
imp * m_imp;
params_ref m_params;
public:
propagate_ineqs_tactic(ast_manager & m, params_ref const & p);
virtual tactic * translate(ast_manager & m) {
return alloc(propagate_ineqs_tactic, m, m_params);
}
virtual ~propagate_ineqs_tactic();
virtual void updt_params(params_ref const & p);
virtual void collect_param_descrs(param_descrs & r) {}
virtual void operator()(goal_ref const & g, goal_ref_buffer & result, model_converter_ref & mc, proof_converter_ref & pc, expr_dependency_ref & core);
virtual void cleanup();
protected:
virtual void set_cancel(bool f);
};
tactic * mk_propagate_ineqs_tactic(ast_manager & m, params_ref const & p) {
return clean(alloc(propagate_ineqs_tactic, m, p));
}
struct propagate_ineqs_tactic::imp {
ast_manager & m;
unsynch_mpq_manager nm;
small_object_allocator m_allocator;
bound_propagator bp;
arith_util m_util;
typedef bound_propagator::var a_var;
obj_map<expr, a_var> m_expr2var;
expr_ref_vector m_var2expr;
typedef numeral_buffer<mpq, unsynch_mpq_manager> mpq_buffer;
typedef svector<a_var> var_buffer;
mpq_buffer m_num_buffer;
var_buffer m_var_buffer;
goal_ref m_new_goal;
imp(ast_manager & _m, params_ref const & p):
m(_m),
m_allocator("ineq-simplifier"),
bp(nm, m_allocator, p),
m_util(m),
m_var2expr(m),
m_num_buffer(nm) {
updt_params_core(p);
}
void updt_params_core(params_ref const & p) {
}
void updt_params(params_ref const & p) {
updt_params_core(p);
bp.updt_params(p);
}
void display_bounds(std::ostream & out) {
unsigned sz = m_var2expr.size();
mpq k;
bool strict;
unsigned ts;
for (unsigned x = 0; x < sz; x++) {
if (bp.lower(x, k, strict, ts))
out << nm.to_string(k) << " " << (strict ? "<" : "<=");
else
out << "-oo <";
out << " " << mk_ismt2_pp(m_var2expr.get(x), m) << " ";
if (bp.upper(x, k, strict, ts))
out << (strict ? "<" : "<=") << " " << nm.to_string(k);
else
out << "< oo";
out << "\n";
}
}
a_var mk_var(expr * t) {
if (m_util.is_to_real(t))
t = to_app(t)->get_arg(0);
a_var x;
if (m_expr2var.find(t, x))
return x;
x = m_var2expr.size();
bp.mk_var(x, m_util.is_int(t));
m_var2expr.push_back(t);
m_expr2var.insert(t, x);
return x;
}
void expr2linear_pol(expr * t, mpq_buffer & as, var_buffer & xs) {
mpq c_mpq_val;
if (m_util.is_add(t)) {
rational c_val;
unsigned num = to_app(t)->get_num_args();
for (unsigned i = 0; i < num; i++) {
expr * mon = to_app(t)->get_arg(i);
expr * c, * x;
if (m_util.is_mul(mon, c, x) && m_util.is_numeral(c, c_val)) {
nm.set(c_mpq_val, c_val.to_mpq());
as.push_back(c_mpq_val);
xs.push_back(mk_var(x));
}
else {
as.push_back(mpq(1));
xs.push_back(mk_var(mon));
}
}
}
else {
as.push_back(mpq(1));
xs.push_back(mk_var(t));
}
nm.del(c_mpq_val);
}
a_var mk_linear_pol(expr * t) {
a_var x;
if (m_expr2var.find(t, x))
return x;
x = mk_var(t);
if (m_util.is_add(t)) {
m_num_buffer.reset();
m_var_buffer.reset();
expr2linear_pol(t, m_num_buffer, m_var_buffer);
m_num_buffer.push_back(mpq(-1));
m_var_buffer.push_back(x);
bp.mk_eq(m_num_buffer.size(), m_num_buffer.c_ptr(), m_var_buffer.c_ptr());
}
return x;
}
enum kind { EQ, LE, GE };
bool process(expr * t) {
bool sign = false;
while (m.is_not(t, t))
sign = !sign;
bool strict = false;
kind k;
if (m.is_eq(t)) {
if (sign)
return false;
k = EQ;
}
else if (m_util.is_le(t)) {
if (sign) {
k = GE;
strict = true;
}
else {
k = LE;
}
}
else if (m_util.is_ge(t)) {
if (sign) {
k = LE;
strict = true;
}
else {
k = GE;
}
}
else {
return false;
}
expr * lhs = to_app(t)->get_arg(0);
expr * rhs = to_app(t)->get_arg(1);
if (m_util.is_numeral(lhs)) {
std::swap(lhs, rhs);
if (k == LE)
k = GE;
else if (k == GE)
k = LE;
}
rational c;
if (!m_util.is_numeral(rhs, c))
return false;
a_var x = mk_linear_pol(lhs);
mpq c_prime;
nm.set(c_prime, c.to_mpq());
if (k == EQ) {
SASSERT(!strict);
bp.assert_lower(x, c_prime, false);
bp.assert_upper(x, c_prime, false);
}
else if (k == LE) {
bp.assert_upper(x, c_prime, strict);
}
else {
SASSERT(k == GE);
bp.assert_lower(x, c_prime, strict);
}
return true;
}
bool collect_bounds(goal const & g) {
bool found = false;
unsigned sz = g.size();
for (unsigned i = 0; i < sz; i++) {
expr * t = g.form(i);
if (process(t))
found = true;
else
m_new_goal->assert_expr(t); // save non-bounds here
}
return found;
}
bool lower_subsumed(expr * p, mpq const & k, bool strict) {
if (!m_util.is_add(p))
return false;
m_num_buffer.reset();
m_var_buffer.reset();
expr2linear_pol(p, m_num_buffer, m_var_buffer);
mpq implied_k;
bool implied_strict;
bool result =
bp.lower(m_var_buffer.size(), m_num_buffer.c_ptr(), m_var_buffer.c_ptr(), implied_k, implied_strict) &&
(nm.gt(implied_k, k) || (nm.eq(implied_k, k) && (!strict || implied_strict)));
nm.del(implied_k);
return result;
}
bool upper_subsumed(expr * p, mpq const & k, bool strict) {
if (!m_util.is_add(p))
return false;
m_num_buffer.reset();
m_var_buffer.reset();
expr2linear_pol(p, m_num_buffer, m_var_buffer);
mpq implied_k;
bool implied_strict;
bool result =
bp.upper(m_var_buffer.size(), m_num_buffer.c_ptr(), m_var_buffer.c_ptr(), implied_k, implied_strict) &&
(nm.lt(implied_k, k) || (nm.eq(implied_k, k) && (!strict || implied_strict)));
nm.del(implied_k);
return result;
}
void restore_bounds() {
mpq l, u;
bool strict_l, strict_u, has_l, has_u;
unsigned ts;
unsigned sz = m_var2expr.size();
for (unsigned x = 0; x < sz; x++) {
expr * p = m_var2expr.get(x);
has_l = bp.lower(x, l, strict_l, ts);
has_u = bp.upper(x, u, strict_u, ts);
if (!has_l && !has_u)
continue;
if (has_l && has_u && nm.eq(l, u) && !strict_l && !strict_u) {
// l <= p <= l --> p = l
m_new_goal->assert_expr(m.mk_eq(p, m_util.mk_numeral(rational(l), m_util.is_int(p))));
continue;
}
if (has_l && !lower_subsumed(p, l, strict_l)) {
if (strict_l)
m_new_goal->assert_expr(m.mk_not(m_util.mk_le(p, m_util.mk_numeral(rational(l), m_util.is_int(p)))));
else
m_new_goal->assert_expr(m_util.mk_ge(p, m_util.mk_numeral(rational(l), m_util.is_int(p))));
}
if (has_u && !upper_subsumed(p, u, strict_u)) {
if (strict_u)
m_new_goal->assert_expr(m.mk_not(m_util.mk_ge(p, m_util.mk_numeral(rational(u), m_util.is_int(p)))));
else
m_new_goal->assert_expr(m_util.mk_le(p, m_util.mk_numeral(rational(u), m_util.is_int(p))));
}
}
}
bool is_x_minus_y_eq_0(expr * t, expr * & x, expr * & y) {
expr * lhs, * rhs, * m1, * m2;
if (m.is_eq(t, lhs, rhs) && m_util.is_zero(rhs) && m_util.is_add(lhs, m1, m2)) {
if (m_util.is_times_minus_one(m2, y) && is_uninterp_const(m1)) {
x = m1;
return true;
}
if (m_util.is_times_minus_one(m1, y) && is_uninterp_const(m2)) {
x = m2;
return true;
}
}
return false;
}
bool is_unbounded(expr * t) {
a_var x;
if (m_expr2var.find(t, x))
return !bp.has_lower(x) && !bp.has_upper(x);
return true;
}
bool lower(expr * t, mpq & k, bool & strict) {
unsigned ts;
a_var x;
if (m_expr2var.find(t, x))
return bp.lower(x, k, strict, ts);
return false;
}
bool upper(expr * t, mpq & k, bool & strict) {
unsigned ts;
a_var x;
if (m_expr2var.find(t, x))
return bp.upper(x, k, strict, ts);
return false;
}
void find_ite_bounds(expr * root) {
TRACE("find_ite_bounds_bug", display_bounds(tout););
expr * n = root;
expr * target = 0;
expr * c, * t, * e;
expr * x, * y;
bool has_l, has_u;
mpq l_min, u_max;
bool l_strict, u_strict;
mpq curr;
bool curr_strict;
while (true) {
TRACE("find_ite_bounds_bug", tout << mk_ismt2_pp(n, m) << "\n";);
if (m.is_ite(n, c, t, e)) {
if (is_x_minus_y_eq_0(t, x, y))
n = e;
else if (is_x_minus_y_eq_0(e, x, y))
n = t;
else
break;
}
else if (is_x_minus_y_eq_0(n, x, y)) {
n = 0;
}
else {
break;
}
TRACE("find_ite_bounds_bug", tout << "x: " << mk_ismt2_pp(x, m) << ", y: " << mk_ismt2_pp(y, m) << "\n";
if (target) {
tout << "target: " << mk_ismt2_pp(target, m) << "\n";
tout << "has_l: " << has_l << " " << nm.to_string(l_min) << " has_u: " << has_u << " " << nm.to_string(u_max) << "\n";
});
if (is_unbounded(y))
std::swap(x, y);
if (!is_unbounded(x)) {
TRACE("find_ite_bounds_bug", tout << "x is already bounded\n";);
break;
}
if (target == 0) {
target = x;
if (lower(y, curr, curr_strict)) {
has_l = true;
nm.set(l_min, curr);
l_strict = curr_strict;
}
else {
has_l = false;
TRACE("find_ite_bounds_bug", tout << "y does not have lower\n";);
}
if (upper(y, curr, curr_strict)) {
has_u = true;
nm.set(u_max, curr);
u_strict = curr_strict;
}
else {
has_u = false;
TRACE("find_ite_bounds_bug", tout << "y does not have upper\n";);
}
}
else if (target == x) {
if (has_l) {
if (lower(y, curr, curr_strict)) {
if (nm.lt(curr, l_min) || (!curr_strict && l_strict && nm.eq(curr, l_min))) {
nm.set(l_min, curr);
l_strict = curr_strict;
}
}
else {
has_l = false;
TRACE("find_ite_bounds_bug", tout << "y does not have lower\n";);
}
}
if (has_u) {
if (upper(y, curr, curr_strict)) {
if (nm.gt(curr, u_max) || (curr_strict && !u_strict && nm.eq(curr, u_max))) {
nm.set(u_max, curr);
u_strict = curr_strict;
}
}
else {
has_u = false;
TRACE("find_ite_bounds_bug", tout << "y does not have upper\n";);
}
}
}
else {
break;
}
if (!has_l && !has_u)
break;
if (n == 0) {
TRACE("find_ite_bounds", tout << "found bounds for: " << mk_ismt2_pp(target, m) << "\n";
tout << "has_l: " << has_l << " " << nm.to_string(l_min) << " l_strict: " << l_strict << "\n";
tout << "has_u: " << has_u << " " << nm.to_string(u_max) << " u_strict: " << u_strict << "\n";
tout << "root:\n" << mk_ismt2_pp(root, m) << "\n";);
a_var x = mk_var(target);
if (has_l)
bp.assert_lower(x, l_min, l_strict);
if (has_u)
bp.assert_upper(x, u_max, u_strict);
break;
}
}
nm.del(l_min);
nm.del(u_max);
nm.del(curr);
}
void find_ite_bounds() {
unsigned sz = m_new_goal->size();
for (unsigned i = 0; i < sz; i++) {
expr * f = m_new_goal->form(i);
if (m.is_ite(f))
find_ite_bounds(to_app(f));
}
bp.propagate();
TRACE("find_ite_bounds", display_bounds(tout););
}
void operator()(goal * g, goal_ref & r) {
tactic_report report("propagate-ineqs", *g);
m_new_goal = alloc(goal, *g, true);
m_new_goal->inc_depth();
r = m_new_goal.get();
if (!collect_bounds(*g)) {
m_new_goal = 0;
r = g;
return; // nothing to be done
}
TRACE("propagate_ineqs_tactic", g->display(tout); display_bounds(tout); tout << "bound propagator:\n"; bp.display(tout););
bp.propagate();
report_tactic_progress(":bound-propagations", bp.get_num_propagations());
report_tactic_progress(":bound-false-alarms", bp.get_num_false_alarms());
if (bp.inconsistent()) {
r->reset();
r->assert_expr(m.mk_false());
return;
}
// find_ite_bounds(); // did not help
restore_bounds();
TRACE("propagate_ineqs_tactic", tout << "after propagation:\n"; display_bounds(tout); bp.display(tout););
TRACE("propagate_ineqs_tactic", r->display(tout););
}
void set_cancel(bool f) {
// TODO
}
};
propagate_ineqs_tactic::propagate_ineqs_tactic(ast_manager & m, params_ref const & p):
m_params(p) {
m_imp = alloc(imp, m, p);
}
propagate_ineqs_tactic::~propagate_ineqs_tactic() {
dealloc(m_imp);
}
void propagate_ineqs_tactic::updt_params(params_ref const & p) {
m_params = p;
m_imp->updt_params(p);
}
void propagate_ineqs_tactic::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());
fail_if_proof_generation("propagate-ineqs", g);
fail_if_unsat_core_generation("propagate-ineqs", g);
mc = 0; pc = 0; core = 0; result.reset();
goal_ref r;
(*m_imp)(g.get(), r);
result.push_back(r.get());
SASSERT(r->is_well_sorted());
}
void propagate_ineqs_tactic::set_cancel(bool f) {
if (m_imp)
m_imp->set_cancel(f);
}
void propagate_ineqs_tactic::cleanup() {
ast_manager & m = m_imp->m;
imp * d = m_imp;
#pragma omp critical (tactic_cancel)
{
d = m_imp;
}
dealloc(d);
d = alloc(imp, m, m_params);
#pragma omp critical (tactic_cancel)
{
m_imp = d;
}
}

View file

@ -0,0 +1,42 @@
/*++
Copyright (c) 2012 Microsoft Corporation
Module Name:
propagate_ineqs_tactic.h
Abstract:
This tactic performs the following tasks:
- Propagate bounds using the bound_propagator.
- Eliminate subsumed inequalities.
For example:
x - y >= 3
can be replaced with true if we know that
x >= 3 and y <= 0
- Convert inequalities of the form p <= k and p >= k into p = k,
where p is a polynomial and k is a constant.
This strategy assumes the input is in arith LHS mode.
This can be achieved by using option :arith-lhs true in the
simplifier.
Author:
Leonardo (leonardo) 2012-02-19
Notes:
--*/
#ifndef _PROPAGATE_INEQS_TACTIC_H_
#define _PROPAGATE_INEQS_TACTIC_H_
#include"params.h"
class ast_manager;
class tactic;
tactic * mk_propagate_ineqs_tactic(ast_manager & m, params_ref const & p = params_ref());
#endif

View file

@ -0,0 +1,909 @@
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
purify_arith_tactic.h
Abstract:
Tactic for eliminating arithmetic operators: DIV, IDIV, MOD,
TO_INT, and optionally (OP_IRRATIONAL_ALGEBRAIC_NUM).
This tactic uses the simplifier for also eliminating:
OP_SUB, OP_UMINUS, OP_POWER (optionally), OP_REM, OP_IS_INT.
Author:
Leonardo de Moura (leonardo) 2011-12-30.
Revision History:
--*/
#include"tactical.h"
#include"rewriter_def.h"
#include"arith_decl_plugin.h"
#include"algebraic_numbers.h"
#include"nnf_tactic.h"
#include"simplify_tactic.h"
#include"th_rewriter.h"
#include"filter_model_converter.h"
#include"ast_smt2_pp.h"
/*
----
Some of the rules needed in the conversion are implemented in
arith_rewriter.cpp. Here is a summary of these rules:
(^ t (/ p q)) --> (^ (^ t (/ 1 q)) p)
(^ t n) --> t*...*t
when integer power expansion is requested
(is-int t) --> t = (to-real (to-int t))
(rem t1 t2) --> ite(t2 >= 0, (mod t1 t2), -(mod t1 t2))
----
The tactic implements a set of transformation rules. These rules
create fresh constants or (existential) variables, and add new
constraints to the context.
The context is the set of asserted formulas or a quantifier.
A rule is represented as:
From --> To | C
It means, any expression that matches From is replaced by To,
and the constraints C are added to the context.
For clarity reasons, I write the constraints using ad-hoc notation.
Rules
(^ t 0) --> k | t != 0 implies k = 1, t = 0 implies k = 0^0
where k is fresh
0^0 is a constant used to capture the meaning of (^ 0 0).
(^ t (/ 1 n)) --> k | t = k^n
when n is odd
where k is fresh
(^ t (/ 1 n)) --> k | t >= 0 implies t = k^n, t < 0 implies t = neg-root(t, n)
when n is even
where k is fresh
neg-root is a function symbol used to capture the meaning of a negative root
(root-obj p(x) i) --> k | p(k) = 0, l < k < u
when root object elimination is requested
where k is fresh
(l, u) is an isolating interval for the i-th root of p.
(to-int t) --> k | 0 <= to-real(k) - t < 1
where k is a fresh integer constant/variable
(/ t1 t2) --> k | t2 != 0 implies k*t2 = t1, t2 = 0 implies k = div-0(t1)
where k is fresh
div-0 is a function symbol used to capture the meaning of division by 0.
Remark: If it can be shown that t2 != 0, then the div-0(t1) function application
vanishes from the formula.
(div t1 t2) --> k1 | t2 = 0 \/ t1 = k1 * t2 + k2,
t2 = 0 \/ 0 <= k2,
t2 = 0 \/ k2 < |t2|,
t2 != 0 \/ k1 = idiv-0(t1),
t2 != 0 \/ k2 = mod-0(t1)
k1 is a fresh name for (div t1 t2)
k2 is a fresh name for (mod t1 t2)
(mod t1 t2) --> k2 | same constraints as above
*/
struct purify_arith_decls {
ast_manager & m;
func_decl * m_int_0_pw_0_decl; // decl for: int 0^0
func_decl * m_real_0_pw_0_decl; // decl for: rel 0^0
func_decl * m_neg_root_decl; // decl for: even root of negative (real) number
func_decl * m_div_0_decl; // decl for: x/0
func_decl * m_idiv_0_decl; // decl for: div(x, 0)
func_decl * m_mod_0_decl; // decl for: mod(x, 0)
func_decl * m_asin_u_decl; // decl for: asin(x) when x < -1 or x > 1
func_decl * m_acos_u_decl; // decl for: acos(x) when x < -1 or x > 1
void inc_refs() {
m.inc_ref(m_int_0_pw_0_decl);
m.inc_ref(m_real_0_pw_0_decl);
m.inc_ref(m_neg_root_decl);
m.inc_ref(m_div_0_decl);
m.inc_ref(m_idiv_0_decl);
m.inc_ref(m_mod_0_decl);
m.inc_ref(m_asin_u_decl);
m.inc_ref(m_acos_u_decl);
}
void dec_refs() {
m.dec_ref(m_int_0_pw_0_decl);
m.dec_ref(m_real_0_pw_0_decl);
m.dec_ref(m_neg_root_decl);
m.dec_ref(m_div_0_decl);
m.dec_ref(m_idiv_0_decl);
m.dec_ref(m_mod_0_decl);
m.dec_ref(m_asin_u_decl);
m.dec_ref(m_acos_u_decl);
}
purify_arith_decls(arith_util & u):
m(u.get_manager()) {
sort * i = u.mk_int();
sort * r = u.mk_real();
m_int_0_pw_0_decl = m.mk_const_decl(symbol("0^0-int"), i);
m_real_0_pw_0_decl = m.mk_const_decl(symbol("0^0-real"), r);
sort * rr[2] = { r, r };
m_neg_root_decl = m.mk_func_decl(symbol("neg-root"), 2, rr, r);
m_div_0_decl = m.mk_func_decl(symbol("/0"), 1, &r, r);
m_idiv_0_decl = m.mk_func_decl(symbol("div0"), 1, &i, i);
m_mod_0_decl = m.mk_func_decl(symbol("mod0"), 1, &i, i);
m_asin_u_decl = m.mk_func_decl(symbol("asin-u"), 1, &r, r);
m_acos_u_decl = m.mk_func_decl(symbol("acos-u"), 1, &r, r);
inc_refs();
}
purify_arith_decls(ast_manager & _m,
func_decl * int_0_pw_0,
func_decl * real_0_pw_0,
func_decl * neg_root,
func_decl * div_0,
func_decl * idiv_0,
func_decl * mod_0,
func_decl * asin_u,
func_decl * acos_u
):
m(_m),
m_int_0_pw_0_decl(int_0_pw_0),
m_real_0_pw_0_decl(real_0_pw_0),
m_neg_root_decl(neg_root),
m_div_0_decl(div_0),
m_idiv_0_decl(idiv_0),
m_mod_0_decl(mod_0),
m_asin_u_decl(asin_u),
m_acos_u_decl(acos_u) {
inc_refs();
}
~purify_arith_decls() {
dec_refs();
}
};
struct purify_arith_proc {
arith_util & m_util;
purify_arith_decls & m_aux_decls;
bool m_produce_proofs;
bool m_elim_root_objs;
bool m_elim_inverses;
bool m_complete;
purify_arith_proc(arith_util & u, purify_arith_decls & d, bool produce_proofs, bool elim_root_objs, bool elim_inverses, bool complete):
m_util(u),
m_aux_decls(d),
m_produce_proofs(produce_proofs),
m_elim_root_objs(elim_root_objs),
m_elim_inverses(elim_inverses),
m_complete(complete) {
}
arith_util & u() {
return m_util;
}
ast_manager & m() {
return u().get_manager();
}
struct rw_cfg : public default_rewriter_cfg {
purify_arith_proc & m_owner;
obj_map<app, expr*> m_app2fresh;
obj_map<app, proof*> m_app2pr;
expr_ref_vector m_pinned;
expr_ref_vector m_new_cnstrs;
proof_ref_vector m_new_cnstr_prs;
expr_ref m_subst;
proof_ref m_subst_pr;
bool m_in_q;
unsigned m_var_idx;
rw_cfg(purify_arith_proc & o, bool in_q):
m_owner(o),
m_pinned(o.m()),
m_new_cnstrs(o.m()),
m_new_cnstr_prs(o.m()),
m_subst(o.m()),
m_subst_pr(o.m()),
m_in_q(in_q),
m_var_idx(0) {
}
ast_manager & m() { return m_owner.m(); }
arith_util & u() { return m_owner.u(); }
bool produce_proofs() const { return m_owner.m_produce_proofs; }
bool complete() const { return m_owner.m_complete; }
bool elim_root_objs() const { return m_owner.m_elim_root_objs; }
bool elim_inverses() const { return m_owner.m_elim_inverses; }
expr * mk_fresh_var(bool is_int) {
if (m_in_q) {
unsigned idx = m_var_idx;
m_var_idx++;
return m().mk_var(idx, is_int ? u().mk_int() : u().mk_real());
}
else {
return m().mk_fresh_const(0, is_int ? u().mk_int() : u().mk_real());
}
}
expr * mk_fresh_real_var() { return mk_fresh_var(false); }
expr * mk_fresh_int_var() { return mk_fresh_var(true); }
func_decl * div0_decl() { return m_owner.m_aux_decls.m_div_0_decl; }
func_decl * idiv0_decl() { return m_owner.m_aux_decls.m_idiv_0_decl; }
func_decl * mod0_decl() { return m_owner.m_aux_decls.m_mod_0_decl; }
func_decl * int_0_pw_0_decl() { return m_owner.m_aux_decls.m_int_0_pw_0_decl; }
func_decl * real_0_pw_0_decl() { return m_owner.m_aux_decls.m_real_0_pw_0_decl; }
func_decl * neg_root_decl() { return m_owner.m_aux_decls.m_neg_root_decl; }
func_decl * asin_u_decl() { return m_owner.m_aux_decls.m_asin_u_decl; }
func_decl * acos_u_decl() { return m_owner.m_aux_decls.m_acos_u_decl; }
expr * mk_int_zero() { return u().mk_numeral(rational(0), true); }
expr * mk_real_zero() { return u().mk_numeral(rational(0), false); }
bool already_processed(app * t, expr_ref & result, proof_ref & result_pr) {
expr * r;
if (m_app2fresh.find(t, r)) {
result = r;
if (produce_proofs())
result_pr = m_app2pr.find(t);
return true;
}
return false;
}
void mk_def_proof(expr * k, expr * def, proof_ref & result_pr) {
result_pr = 0;
if (produce_proofs()) {
expr * eq = m().mk_eq(k, def);
proof * pr1 = m().mk_def_intro(eq);
result_pr = m().mk_apply_def(k, def, pr1);
}
}
void push_cnstr_pr(proof * def_pr) {
if (produce_proofs())
m_new_cnstr_prs.push_back(m().mk_th_lemma(u().get_family_id(), m_new_cnstrs.back(), 1, &def_pr));
}
void push_cnstr_pr(proof * def_pr1, proof * def_pr2) {
if (produce_proofs()) {
proof * prs[2] = { def_pr1, def_pr2 };
m_new_cnstr_prs.push_back(m().mk_th_lemma(u().get_family_id(), m_new_cnstrs.back(), 2, prs));
}
}
void push_cnstr(expr * cnstr) {
m_new_cnstrs.push_back(cnstr);
}
void cache_result(app * t, expr * r, proof * pr) {
m_app2fresh.insert(t, r);
m_pinned.push_back(t);
m_pinned.push_back(r);
if (produce_proofs()) {
m_app2pr.insert(t, pr);
m_pinned.push_back(pr);
}
}
expr * OR(expr * arg1, expr * arg2) { return m().mk_or(arg1, arg2); }
expr * AND(expr * arg1, expr * arg2) { return m().mk_and(arg1, arg2); }
expr * EQ(expr * lhs, expr * rhs) { return m().mk_eq(lhs, rhs); }
expr * NOT(expr * arg) { return m().mk_not(arg); }
void process_div(func_decl * f, unsigned num, expr * const * args, expr_ref & result, proof_ref & result_pr) {
app_ref t(m());
t = m().mk_app(f, num, args);
if (already_processed(t, result, result_pr))
return;
expr * k = mk_fresh_real_var();
result = k;
mk_def_proof(k, t, result_pr);
cache_result(t, result, result_pr);
expr * x = args[0];
expr * y = args[1];
// y = 0 \/ y*k = x
push_cnstr(OR(EQ(y, mk_real_zero()),
EQ(u().mk_mul(y, k), x)));
push_cnstr_pr(result_pr);
if (complete()) {
// y != 0 \/ k = div-0(x)
push_cnstr(OR(NOT(EQ(y, mk_real_zero())),
EQ(k, m().mk_app(div0_decl(), x))));
push_cnstr_pr(result_pr);
}
}
void process_idiv(func_decl * f, unsigned num, expr * const * args, expr_ref & result, proof_ref & result_pr) {
app_ref div_app(m());
div_app = m().mk_app(f, num, args);
if (already_processed(div_app, result, result_pr))
return;
expr * k1 = mk_fresh_int_var();
result = k1;
mk_def_proof(k1, div_app, result_pr);
cache_result(div_app, result, result_pr);
expr * k2 = mk_fresh_int_var();
app_ref mod_app(m());
proof_ref mod_pr(m());
mod_app = u().mk_mod(args[0], args[1]);
mk_def_proof(k2, mod_app, mod_pr);
cache_result(mod_app, k2, mod_pr);
expr * x = args[0];
expr * y = args[1];
// (div x y) --> k1 | y = 0 \/ x = k1 * y + k2,
// y = 0 \/ 0 <= k2,
// y = 0 \/ k2 < |y|,
// y != 0 \/ k1 = idiv-0(x),
// y != 0 \/ k2 = mod-0(x)
// We can write y = 0 \/ k2 < |y| as:
// y > 0 implies k2 < y ---> y <= 0 \/ k2 < y
// y < 0 implies k2 < -y ---> y >= 0 \/ k2 < -y
//
expr * zero = mk_int_zero();
push_cnstr(OR(EQ(y, zero), EQ(x, u().mk_add(u().mk_mul(k1, y), k2))));
push_cnstr_pr(result_pr, mod_pr);
push_cnstr(OR(EQ(y, zero), u().mk_le(zero, k2)));
push_cnstr_pr(mod_pr);
push_cnstr(OR(u().mk_le(y, zero), u().mk_lt(k2, y)));
push_cnstr_pr(mod_pr);
push_cnstr(OR(u().mk_ge(y, zero), u().mk_lt(k2, u().mk_mul(u().mk_numeral(rational(-1), true), y))));
push_cnstr_pr(mod_pr);
if (complete()) {
push_cnstr(OR(NOT(EQ(y, zero)), EQ(k1, m().mk_app(idiv0_decl(), x))));
push_cnstr_pr(result_pr);
push_cnstr(OR(NOT(EQ(y, zero)), EQ(k2, m().mk_app(mod0_decl(), x))));
push_cnstr_pr(mod_pr);
}
}
void process_mod(func_decl * f, unsigned num, expr * const * args, expr_ref & result, proof_ref & result_pr) {
app_ref t(m());
t = m().mk_app(f, num, args);
if (already_processed(t, result, result_pr))
return;
process_idiv(f, num, args, result, result_pr); // it will create mod
VERIFY(already_processed(t, result, result_pr));
}
void process_to_int(func_decl * f, unsigned num, expr * const * args, expr_ref & result, proof_ref & result_pr) {
app_ref t(m());
t = m().mk_app(f, num, args);
if (already_processed(t, result, result_pr))
return;
expr * k = mk_fresh_int_var();
result = k;
mk_def_proof(k, t, result_pr);
cache_result(t, result, result_pr);
expr * x = args[0];
// to-real(k) - x >= 0
expr * diff = u().mk_add(u().mk_to_real(k), u().mk_mul(u().mk_numeral(rational(-1), false), x));
push_cnstr(u().mk_ge(diff, mk_real_zero()));
push_cnstr_pr(result_pr);
// not(to-real(k) - x >= 1)
push_cnstr(NOT(u().mk_ge(diff, u().mk_numeral(rational(1), false))));
push_cnstr_pr(result_pr);
}
br_status process_power(func_decl * f, unsigned num, expr * const * args, expr_ref & result, proof_ref & result_pr) {
rational y;
if (!u().is_numeral(args[1], y))
return BR_FAILED;
if (y.is_int() && !y.is_zero())
return BR_FAILED;
app_ref t(m());
t = m().mk_app(f, num, args);
if (already_processed(t, result, result_pr))
return BR_DONE;
bool is_int = u().is_int(args[0]);
expr * k = mk_fresh_var(is_int);
result = k;
mk_def_proof(k, t, result_pr);
cache_result(t, result, result_pr);
expr * x = args[0];
expr * zero = u().mk_numeral(rational(0), is_int);
expr * one = u().mk_numeral(rational(1), is_int);
if (y.is_zero()) {
// (^ x 0) --> k | x != 0 implies k = 1, x = 0 implies k = 0^0
push_cnstr(OR(EQ(x, zero), EQ(k, one)));
push_cnstr_pr(result_pr);
if (complete()) {
func_decl * z_pw_z = is_int ? int_0_pw_0_decl() : real_0_pw_0_decl();
push_cnstr(OR(NOT(EQ(x, zero)), EQ(k, m().mk_const(z_pw_z))));
push_cnstr_pr(result_pr);
}
}
else if (!is_int) {
SASSERT(!y.is_int());
SASSERT(numerator(y).is_one());
rational n = denominator(y);
if (!n.is_even()) {
// (^ x (/ 1 n)) --> k | x = k^n
// when n is odd
push_cnstr(EQ(x, u().mk_power(k, u().mk_numeral(n, false))));
push_cnstr_pr(result_pr);
}
else {
SASSERT(n.is_even());
// (^ x (/ 1 n)) --> k | x >= 0 implies (x = k^n and k >= 0), x < 0 implies k = neg-root(x, n)
// when n is even
push_cnstr(OR(NOT(u().mk_ge(x, zero)),
AND(EQ(x, u().mk_power(k, u().mk_numeral(n, false))),
u().mk_ge(k, zero))));
push_cnstr_pr(result_pr);
if (complete()) {
push_cnstr(OR(u().mk_ge(x, zero),
EQ(k, m().mk_app(neg_root_decl(), x, u().mk_numeral(n, false)))));
push_cnstr_pr(result_pr);
}
}
}
else {
// root not supported for integers.
SASSERT(is_int);
SASSERT(!y.is_int());
return BR_FAILED;
}
return BR_DONE;
}
void process_irrat(app * s, expr_ref & result, proof_ref & result_pr) {
if (already_processed(s, result, result_pr))
return;
expr * k = mk_fresh_real_var();
result = k;
mk_def_proof(k, s, result_pr);
cache_result(s, result, result_pr);
anum_manager & am = u().am();
anum const & a = u().to_irrational_algebraic_numeral(s);
scoped_mpz_vector p(am.qm());
am.get_polynomial(a, p);
rational lower, upper;
am.get_lower(a, lower);
am.get_upper(a, upper);
unsigned sz = p.size();
SASSERT(sz > 2);
ptr_buffer<expr> args;
for (unsigned i = 0; i < sz; i++) {
if (am.qm().is_zero(p[i]))
continue;
rational coeff = rational(p[i]);
if (i == 0) {
args.push_back(u().mk_numeral(coeff, false));
}
else {
expr * m;
if (i == 1)
m = k;
else
m = u().mk_power(k, u().mk_numeral(rational(i), false));
args.push_back(u().mk_mul(u().mk_numeral(coeff, false), m));
}
}
SASSERT(args.size() >= 2);
push_cnstr(EQ(u().mk_add(args.size(), args.c_ptr()), mk_real_zero()));
push_cnstr_pr(result_pr);
push_cnstr(u().mk_lt(u().mk_numeral(lower, false), k));
push_cnstr_pr(result_pr);
push_cnstr(u().mk_lt(k, u().mk_numeral(upper, false)));
push_cnstr_pr(result_pr);
}
br_status process_asin(func_decl * f, expr * x, expr_ref & result, proof_ref & result_pr) {
if (!elim_inverses())
return BR_FAILED;
app_ref t(m());
t = m().mk_app(f, x);
if (already_processed(t, result, result_pr))
return BR_DONE;
expr * k = mk_fresh_var(false);
result = k;
mk_def_proof(k, t, result_pr);
cache_result(t, result, result_pr);
// Constraints:
// -1 <= x <= 1 implies sin(k) = x, -pi/2 <= k <= pi/2
// If complete()
// x < -1 implies k = asin_u(x)
// x > 1 implies k = asin_u(x)
expr * one = u().mk_numeral(rational(1), false);
expr * mone = u().mk_numeral(rational(-1), false);
expr * pi2 = u().mk_mul(u().mk_numeral(rational(1,2), false), u().mk_pi());
expr * mpi2 = u().mk_mul(u().mk_numeral(rational(-1,2), false), u().mk_pi());
// -1 <= x <= 1 implies sin(k) = x, -pi/2 <= k <= pi/2
push_cnstr(OR(OR(NOT(u().mk_ge(x, mone)),
NOT(u().mk_le(x, one))),
AND(EQ(x, u().mk_sin(k)),
AND(u().mk_ge(k, mpi2),
u().mk_le(k, pi2)))));
push_cnstr_pr(result_pr);
if (complete()) {
// x < -1 implies k = asin_u(x)
// x > 1 implies k = asin_u(x)
push_cnstr(OR(u().mk_ge(x, mone),
EQ(k, m().mk_app(asin_u_decl(), x))));
push_cnstr_pr(result_pr);
push_cnstr(OR(u().mk_le(x, one),
EQ(k, m().mk_app(asin_u_decl(), x))));
push_cnstr_pr(result_pr);
}
return BR_DONE;
}
br_status process_acos(func_decl * f, expr * x, expr_ref & result, proof_ref & result_pr) {
if (!elim_inverses())
return BR_FAILED;
app_ref t(m());
t = m().mk_app(f, x);
if (already_processed(t, result, result_pr))
return BR_DONE;
expr * k = mk_fresh_var(false);
result = k;
mk_def_proof(k, t, result_pr);
cache_result(t, result, result_pr);
// Constraints:
// -1 <= x <= 1 implies cos(k) = x, 0 <= k <= pi
// If complete()
// x < -1 implies k = acos_u(x)
// x > 1 implies k = acos_u(x)
expr * one = u().mk_numeral(rational(1), false);
expr * mone = u().mk_numeral(rational(-1), false);
expr * pi = u().mk_pi();
expr * zero = u().mk_numeral(rational(0), false);
// -1 <= x <= 1 implies cos(k) = x, 0 <= k <= pi
push_cnstr(OR(OR(NOT(u().mk_ge(x, mone)),
NOT(u().mk_le(x, one))),
AND(EQ(x, u().mk_cos(k)),
AND(u().mk_ge(k, zero),
u().mk_le(k, pi)))));
push_cnstr_pr(result_pr);
if (complete()) {
// x < -1 implies k = acos_u(x)
// x > 1 implies k = acos_u(x)
push_cnstr(OR(u().mk_ge(x, mone),
EQ(k, m().mk_app(acos_u_decl(), x))));
push_cnstr_pr(result_pr);
push_cnstr(OR(u().mk_le(x, one),
EQ(k, m().mk_app(acos_u_decl(), x))));
push_cnstr_pr(result_pr);
}
return BR_DONE;
}
br_status process_atan(func_decl * f, expr * x, expr_ref & result, proof_ref & result_pr) {
if (!elim_inverses())
return BR_FAILED;
app_ref t(m());
t = m().mk_app(f, x);
if (already_processed(t, result, result_pr))
return BR_DONE;
expr * k = mk_fresh_var(false);
result = k;
mk_def_proof(k, t, result_pr);
cache_result(t, result, result_pr);
// Constraints:
// tan(k) = x, -pi/2 < k < pi/2
expr * pi2 = u().mk_mul(u().mk_numeral(rational(1,2), false), u().mk_pi());
expr * mpi2 = u().mk_mul(u().mk_numeral(rational(-1,2), false), u().mk_pi());
push_cnstr(AND(EQ(x, u().mk_tan(k)),
AND(u().mk_gt(k, mpi2),
u().mk_lt(k, pi2))));
push_cnstr_pr(result_pr);
return BR_DONE;
}
br_status reduce_app(func_decl * f, unsigned num, expr * const * args, expr_ref & result, proof_ref & result_pr) {
if (f->get_family_id() != u().get_family_id())
return BR_FAILED;
switch (f->get_decl_kind()) {
case OP_DIV:
process_div(f, num, args, result, result_pr);
return BR_DONE;
case OP_IDIV:
process_idiv(f, num, args, result, result_pr);
return BR_DONE;
case OP_MOD:
process_mod(f, num, args, result, result_pr);
return BR_DONE;
case OP_TO_INT:
process_to_int(f, num, args, result, result_pr);
return BR_DONE;
case OP_POWER:
return process_power(f, num, args, result, result_pr);
case OP_ASIN:
return process_asin(f, args[0], result, result_pr);
case OP_ACOS:
return process_acos(f, args[0], result, result_pr);
case OP_ATAN:
return process_atan(f, args[0], result, result_pr);
default:
return BR_FAILED;
}
}
bool get_subst(expr * s, expr * & t, proof * & t_pr) {
if (is_quantifier(s)) {
m_owner.process_quantifier(to_quantifier(s), m_subst, m_subst_pr);
t = m_subst.get();
t_pr = m_subst_pr.get();
return true;
}
else if (u().is_irrational_algebraic_numeral(s) && elim_root_objs()) {
process_irrat(to_app(s), m_subst, m_subst_pr);
t = m_subst.get();
t_pr = m_subst_pr.get();
return true;
}
return false;
}
};
struct rw : public rewriter_tpl<rw_cfg> {
rw_cfg m_cfg;
rw(purify_arith_proc & o, bool in_q):
rewriter_tpl<rw_cfg>(o.m(), o.m_produce_proofs, m_cfg),
m_cfg(o, in_q) {
}
};
/**
\brief Return the number of (auxiliary) variables needed for converting an expression.
*/
struct num_vars_proc {
arith_util & m_util;
expr_fast_mark1 m_visited;
ptr_vector<expr> m_todo;
unsigned m_num_vars;
bool m_elim_root_objs;
num_vars_proc(arith_util & u, bool elim_root_objs):
m_util(u),
m_elim_root_objs(elim_root_objs) {
}
void visit(expr * t) {
if (m_visited.is_marked(t))
return;
m_visited.mark(t);
m_todo.push_back(t);
}
void process(app * t) {
if (t->get_family_id() == m_util.get_family_id()) {
if (m_util.is_power(t)) {
rational k;
if (m_util.is_numeral(t->get_arg(1), k) && (k.is_zero() || !k.is_int())) {
m_num_vars++;
}
}
else if (m_util.is_div(t) ||
m_util.is_idiv(t) ||
m_util.is_mod(t) ||
m_util.is_to_int(t) ||
(m_util.is_irrational_algebraic_numeral(t) && m_elim_root_objs)) {
m_num_vars++;
}
}
unsigned num_args = t->get_num_args();
for (unsigned i = 0; i < num_args; i++)
visit(t->get_arg(i));
}
unsigned operator()(expr * t) {
m_num_vars = 0;
visit(t);
while (!m_todo.empty()) {
expr * t = m_todo.back();
m_todo.pop_back();
if (is_app(t))
process(to_app(t));
}
m_visited.reset();
return m_num_vars;
}
};
void process_quantifier(quantifier * q, expr_ref & result, proof_ref & result_pr) {
result_pr = 0;
num_vars_proc p(u(), m_elim_root_objs);
expr_ref body(m());
unsigned num_vars = p(q->get_expr());
if (num_vars > 0) {
// open space for aux vars
var_shifter shifter(m());
shifter(q->get_expr(), num_vars, body);
}
else {
body = q->get_expr();
}
rw r(*this, true);
expr_ref new_body(m());
proof_ref new_body_pr(m());
r(body, new_body, new_body_pr);
TRACE("purify_arith",
tout << "num_vars: " << num_vars << "\n";
tout << "body: " << mk_ismt2_pp(body, m()) << "\nnew_body: " << mk_ismt2_pp(new_body, m()) << "\n";);
if (num_vars == 0) {
result = m().update_quantifier(q, new_body);
if (m_produce_proofs)
result_pr = m().mk_quant_intro(q, to_quantifier(result.get()), result_pr);
}
else {
expr_ref_vector & cnstrs = r.cfg().m_new_cnstrs;
cnstrs.push_back(new_body);
new_body = m().mk_and(cnstrs.size(), cnstrs.c_ptr());
ptr_buffer<sort> sorts;
buffer<symbol> names;
for (unsigned i = 0; i < num_vars; i++) {
sorts.push_back(u().mk_real());
names.push_back(m().mk_fresh_var_name("x"));
}
new_body = m().mk_exists(num_vars, sorts.c_ptr(), names.c_ptr(), new_body);
result = m().update_quantifier(q, new_body);
if (m_produce_proofs) {
proof_ref_vector & cnstr_prs = r.cfg().m_new_cnstr_prs;
cnstr_prs.push_back(result_pr);
// TODO: improve proof
result_pr = m().mk_quant_intro(q, to_quantifier(result.get()),
m().mk_rewrite_star(q->get_expr(), new_body, cnstr_prs.size(), cnstr_prs.c_ptr()));
}
}
}
void operator()(goal & g, model_converter_ref & mc, bool produce_models) {
rw r(*this, false);
// purify
expr_ref new_curr(m());
proof_ref new_pr(m());
unsigned sz = g.size();
for (unsigned i = 0; i < sz; i++) {
expr * curr = g.form(i);
r(curr, new_curr, new_pr);
if (m_produce_proofs) {
proof * pr = g.pr(i);
new_pr = m().mk_modus_ponens(pr, new_pr);
}
g.update(i, new_curr, new_pr, g.dep(i));
}
// add cnstraints
sz = r.cfg().m_new_cnstrs.size();
for (unsigned i = 0; i < sz; i++) {
g.assert_expr(r.cfg().m_new_cnstrs.get(i), m_produce_proofs ? r.cfg().m_new_cnstr_prs.get(i) : 0, 0);
}
// add filter_model_converter to eliminate auxiliary variables from model
if (produce_models) {
filter_model_converter * fmc = alloc(filter_model_converter, m());
mc = fmc;
obj_map<app, expr*> & f2v = r.cfg().m_app2fresh;
obj_map<app, expr*>::iterator it = f2v.begin();
obj_map<app, expr*>::iterator end = f2v.end();
for (; it != end; ++it) {
app * v = to_app(it->m_value);
SASSERT(is_uninterp_const(v));
fmc->insert(v->get_decl());
}
}
}
};
class purify_arith_tactic : public tactic {
arith_util m_util;
purify_arith_decls m_aux_decls;
params_ref m_params;
public:
purify_arith_tactic(ast_manager & m, params_ref const & p):
m_util(m),
m_aux_decls(m_util),
m_params(p) {
}
virtual tactic * translate(ast_manager & m) {
return alloc(purify_arith_tactic, m, m_params);
}
virtual ~purify_arith_tactic() {
}
virtual void updt_params(params_ref const & p) {
m_params = p;
}
virtual void collect_param_descrs(param_descrs & r) {
r.insert(":complete", CPK_BOOL,
"(default: true) add constraints to make sure that any interpretation of a underspecified arithmetic operators is a functio. The result will include additional uninterpreted functions/constants: /0, div0, mod0, 0^0, neg-root");
r.insert(":elim-root-objects", CPK_BOOL,
"(default: true) eliminate root objects.");
r.insert(":elim-inverses", CPK_BOOL,
"(default: true) eliminate inverse trigonometric functions (asin, acos, atan).");
th_rewriter::get_param_descrs(r);
}
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());
mc = 0; pc = 0; core = 0;
tactic_report report("purify-arith", *g);
bool produce_proofs = g->proofs_enabled();
bool produce_models = g->models_enabled();
bool elim_root_objs = m_params.get_bool(":elim-root-objects", true);
bool elim_inverses = m_params.get_bool(":elim-inverses", true);
bool complete = m_params.get_bool(":complete", true);
purify_arith_proc proc(m_util, m_aux_decls, produce_proofs, elim_root_objs, elim_inverses, complete);
proc(*(g.get()), mc, produce_models);
g->inc_depth();
result.push_back(g.get());
TRACE("purify_arith", g->display(tout););
SASSERT(g->is_well_sorted());
}
virtual void cleanup() {
}
virtual void set_cancel(bool f) {
}
};
tactic * mk_purify_arith_tactic(ast_manager & m, params_ref const & p) {
params_ref elim_rem_p = p;
elim_rem_p.set_bool(":elim-rem", true);
params_ref skolemize_p;
skolemize_p.set_bool(":skolemize", false);
return and_then(using_params(mk_snf_tactic(m, skolemize_p), skolemize_p),
using_params(mk_simplify_tactic(m, elim_rem_p), elim_rem_p),
alloc(purify_arith_tactic, m, p),
mk_simplify_tactic(m, p));
}

View file

@ -0,0 +1,58 @@
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
purify_arith_tactic.h
Abstract:
Tactic for eliminating arithmetic operators: DIV, IDIV, MOD,
TO_INT, and optionally (OP_IRRATIONAL_ALGEBRAIC_NUM).
This tactic uses the simplifier for also eliminating:
OP_SUB, OP_UMINUS, OP_POWER (optionally), OP_REM, OP_IS_INT.
Remarks:
- The semantics of division by zero is not specified. Thus,
uninterpreted functions are used. An ExRCF procedure may
treat the unintepreted function applications as fresh
constants. Then, in any model produced by this procedure,
the interpretation for division by zero must be checked.
- POWER operator can only be handled if the second argument is a
rational value. The tactic has an option for preserving POWER
operator where the second argument is an integer.
- The semantics of (^ t (/ 1 k)) is not specified when t < 0 and
k is even. Similarly to the division by zero case,
uninterpreted function symbols are created.
- The semantics of (^ t 0) is not specified if t == 0. Thus,
uninterpreted function symbols are created.
- TO_REAL is not really outside of the RCF language
since it is only used for "casting".
- All quantifiers must occur with positive polarity.
The tactic snf (with skolemization disabled) is applied
to enforce that.
Author:
Leonardo de Moura (leonardo) 2011-12-30.
Revision History:
--*/
#ifndef _PURIFY_ARITH_TACTIC_H_
#define _PURIFY_ARITH_TACTIC_H_
#include"params.h"
class ast_manager;
class tactic;
tactic * mk_purify_arith_tactic(ast_manager & m, params_ref const & p = params_ref());
#endif

View file

@ -0,0 +1,446 @@
/*++
Copyright (c) 2012 Microsoft Corporation
Module Name:
recover_01_tactic.cpp
Abstract:
Recover 01 variables
Search for clauses of the form
p or q or x = 0
~p or q or x = k1
p or ~q or x = k2
~p or ~q or x = k1+k2
Then, replaces
x with k1*y1 + k2*y2
p with y1=1
q with y2=1
where y1 and y2 are fresh 01 variables
The clauses are also removed.
Author:
Leonardo de Moura (leonardo) 2012-02-17.
Revision History:
--*/
#include"tactical.h"
#include"th_rewriter.h"
#include"extension_model_converter.h"
#include"filter_model_converter.h"
#include"arith_decl_plugin.h"
#include"expr_substitution.h"
#include"dec_ref_util.h"
#include"ast_smt2_pp.h"
class recover_01_tactic : public tactic {
struct imp {
typedef obj_map<func_decl, ptr_vector<app> > var2clauses;
ast_manager & m;
var2clauses m_var2clauses;
arith_util m_util;
th_rewriter m_rw;
bool m_produce_models;
unsigned m_cls_max_size;
imp(ast_manager & _m, params_ref const & p):
m(_m),
m_util(m),
m_rw(m, p) {
updt_params_core(p);
}
void updt_params_core(params_ref const & p) {
m_cls_max_size = p.get_uint(":recover-01-max-bits", 10);
}
void updt_params(params_ref const & p) {
m_rw.updt_params(p);
updt_params_core(p);
}
void set_cancel(bool f) {
m_rw.set_cancel(f);
}
bool save_clause(expr * c) {
if (!m.is_or(c))
return false;
func_decl * x = 0;
app * cls = to_app(c);
if (cls->get_num_args() <= 1 || cls->get_num_args() >= m_cls_max_size)
return false;
unsigned sz = cls->get_num_args();
for (unsigned i = 0; i < sz; i++) {
expr * lit = cls->get_arg(i);
expr * lhs, * rhs, * arg;
if (is_uninterp_const(lit)) {
// positive literal
}
else if (m.is_not(lit, arg) && is_uninterp_const(arg)) {
// negative literal
}
else if (x == 0 && m.is_eq(lit, lhs, rhs)) {
// x = k literal
if (is_uninterp_const(lhs) && m_util.is_numeral(rhs)) {
x = to_app(lhs)->get_decl();
}
else if (is_uninterp_const(rhs) && m_util.is_numeral(lhs)) {
x = to_app(rhs)->get_decl();
}
else {
return false;
}
}
else {
return false;
}
}
if (x != 0) {
var2clauses::obj_map_entry * entry = m_var2clauses.insert_if_not_there2(x, ptr_vector<app>());
if (entry->get_data().m_value.empty() || entry->get_data().m_value.back()->get_num_args() == cls->get_num_args()) {
entry->get_data().m_value.push_back(cls);
return true;
}
}
return false;
}
// temporary fields used by operator() and process
extension_model_converter * mc1;
filter_model_converter * mc2;
expr_substitution * subst;
goal_ref new_goal;
obj_map<expr, expr *> bool2int;
app * find_zero_cls(func_decl * x, ptr_vector<app> & clauses) {
ptr_vector<app>::iterator it = clauses.begin();
ptr_vector<app>::iterator end = clauses.end();
for (; it != end; ++it) {
app * cls = *it;
unsigned num = cls->get_num_args();
for (unsigned i = 0; i < num; i++) {
expr * lhs, * rhs;
if (m.is_eq(cls->get_arg(i), lhs, rhs)) {
if (is_uninterp_const(lhs) && m_util.is_zero(rhs))
return cls;
if (is_uninterp_const(rhs) && m_util.is_zero(lhs))
return cls;
}
}
}
return 0;
}
// Find coeff (the k of literal (x = k)) of clause cls.
// Store in idx the bit-vector representing the literals.
// Example: idx = 101 if cls has three boolean literals p1, p2, p3
// where p1 = ~q1, p2 = q2, p3 = ~q3
// and q1 q2 q3 are the corresponding literals in the
// zero clause.
// Return false, if the boolean literals of cls cannot be matched with the literals
// of zero_cls
bool find_coeff(app * cls, app * zero_cls, unsigned & idx, rational & k) {
unsigned num = zero_cls->get_num_args();
if (cls->get_num_args() != num)
return false;
idx = 0;
unsigned val = 1;
for (unsigned i = 0; i < num; i++) {
expr * lit = zero_cls->get_arg(i);
if (m.is_eq(lit))
continue;
// search for lit or ~lit in cls
unsigned j;
for (j = 0; j < num; j++) {
expr * lit2 = cls->get_arg(j);
if (m.is_eq(lit2))
continue;
if (lit2 == lit)
break;
if (m.is_complement(lit2, lit)) {
idx += val;
break;
}
}
if (j == num)
return false; // cls does not contain literal lit
val *= 2;
}
// find k
unsigned i;
for (i = 0; i < num; i++) {
expr * lhs, * rhs;
if (m.is_eq(cls->get_arg(i), lhs, rhs) && (m_util.is_numeral(lhs, k) || m_util.is_numeral(rhs, k)))
break;
}
if (i == num)
return false;
return true;
}
void mk_ivar(expr * lit, expr_ref & def, bool real_ctx) {
expr * atom;
bool sign;
if (m.is_not(lit, atom)) {
sign = true;
}
else {
atom = lit;
sign = false;
}
SASSERT(is_uninterp_const(atom));
expr * var;
if (!bool2int.find(atom, var)) {
var = m.mk_fresh_const(0, m_util.mk_int());
new_goal->assert_expr(m_util.mk_le(m_util.mk_numeral(rational(0), true), var));
new_goal->assert_expr(m_util.mk_le(var, m_util.mk_numeral(rational(1), true)));
expr * bool_def = m.mk_eq(var, m_util.mk_numeral(rational(1), true));
subst->insert(atom, bool_def);
if (m_produce_models) {
mc2->insert(to_app(var)->get_decl());
mc1->insert(to_app(atom)->get_decl(), bool_def);
}
m.inc_ref(atom);
m.inc_ref(var);
bool2int.insert(atom, var);
}
expr * norm_var = real_ctx ? m_util.mk_to_real(var) : var;
if (sign)
def = m_util.mk_sub(m_util.mk_numeral(rational(1), !real_ctx), norm_var);
else
def = norm_var;
}
bool process(func_decl * x, ptr_vector<app> & clauses) {
unsigned cls_size = clauses.back()->get_num_args();
unsigned expected_num_clauses = 1 << (cls_size - 1);
if (clauses.size() < expected_num_clauses) // using < instead of != because we tolerate duplicates
return false;
app * zero_cls = find_zero_cls(x, clauses);
if (zero_cls == 0)
return false;
buffer<bool> found; // marks which idx were found
buffer<rational> idx2coeff;
found.resize(expected_num_clauses, false);
idx2coeff.resize(expected_num_clauses);
ptr_vector<app>::iterator it = clauses.begin();
ptr_vector<app>::iterator end = clauses.end();
for (; it != end; ++it) {
app * cls = *it;
unsigned idx; rational k;
if (!find_coeff(cls, zero_cls, idx, k))
return false;
SASSERT(idx < expected_num_clauses);
if (found[idx] && k != idx2coeff[idx])
return false;
found[idx] = true;
idx2coeff[idx] = k;
}
unsigned num_bits = cls_size - 1;
// check if idxs are consistent
for (unsigned idx = 0; idx < expected_num_clauses; idx++) {
if (!found[idx])
return false; // case is missing
rational expected_k;
unsigned idx_aux = idx;
unsigned idx_bit = 1;
for (unsigned j = 0; j < num_bits; j++) {
if (idx_aux % 2 == 1) {
expected_k += idx2coeff[idx_bit];
}
idx_aux /= 2;
idx_bit *= 2;
}
if (idx2coeff[idx] != expected_k)
return false;
}
expr_ref_buffer def_args(m);
expr_ref def(m);
bool real_ctx = m_util.is_real(x->get_range());
unsigned idx_bit = 1;
for (unsigned i = 0; i < cls_size; i++) {
expr * lit = zero_cls->get_arg(i);
if (m.is_eq(lit))
continue;
mk_ivar(lit, def, real_ctx);
def_args.push_back(m_util.mk_mul(m_util.mk_numeral(idx2coeff[idx_bit], !real_ctx), def));
idx_bit *= 2;
}
expr * x_def;
if (def_args.size() == 1)
x_def = def_args[0];
else
x_def = m_util.mk_add(def_args.size(), def_args.c_ptr());
TRACE("recover_01", tout << x->get_name() << " --> " << mk_ismt2_pp(x_def, m) << "\n";);
subst->insert(m.mk_const(x), x_def);
if (m_produce_models) {
mc1->insert(x, x_def);
}
return true;
}
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());
fail_if_proof_generation("recover-01", g);
fail_if_unsat_core_generation("recover-01", g);
m_produce_models = g->models_enabled();
mc = 0; pc = 0; core = 0; result.reset();
tactic_report report("recover-01", *g);
bool saved = false;
new_goal = alloc(goal, *g, true);
SASSERT(new_goal->depth() == g->depth());
SASSERT(new_goal->prec() == g->prec());
new_goal->inc_depth();
unsigned sz = g->size();
for (unsigned i = 0; i < sz; i++) {
expr * f = g->form(i);
if (save_clause(f)) {
saved = true;
}
else {
new_goal->assert_expr(f);
}
}
if (!saved) {
result.push_back(g.get());
return;
}
if (m_produce_models) {
mc1 = alloc(extension_model_converter, m);
mc2 = alloc(filter_model_converter, m);
mc = concat(mc2, mc1);
}
dec_ref_key_values(m, bool2int);
unsigned counter = 0;
bool recovered = false;
expr_substitution _subst(m);
subst = &_subst;
var2clauses::iterator it = m_var2clauses.begin();
var2clauses::iterator end = m_var2clauses.end();
for (; it != end; ++it) {
if (process(it->m_key, it->m_value)) {
recovered = true;
counter++;
}
else {
ptr_vector<app>::iterator it2 = it->m_value.begin();
ptr_vector<app>::iterator end2 = it->m_value.end();
for (; it2 != end2; ++it2) {
new_goal->assert_expr(*it2);
}
}
}
if (!recovered) {
result.push_back(g.get());
mc = 0;
return;
}
report_tactic_progress(":recovered-01-vars", counter);
m_rw.set_substitution(subst);
expr_ref new_curr(m);
proof_ref new_pr(m);
unsigned size = new_goal->size();
for (unsigned idx = 0; idx < size; idx++) {
expr * curr = new_goal->form(idx);
m_rw(curr, new_curr);
new_goal->update(idx, new_curr);
}
result.push_back(new_goal.get());
TRACE("recover_01", new_goal->display(tout););
SASSERT(new_goal->is_well_sorted());
}
~imp() {
dec_ref_key_values(m, bool2int);
}
};
imp * m_imp;
params_ref m_params;
public:
recover_01_tactic(ast_manager & m, params_ref const & p):
m_params(p) {
m_imp = alloc(imp, m, p);
}
virtual tactic * translate(ast_manager & m) {
return alloc(recover_01_tactic, m, m_params);
}
virtual ~recover_01_tactic() {
dealloc(m_imp);
}
virtual void updt_params(params_ref const & p) {
m_params = p;
m_imp->updt_params(p);
}
virtual void collect_param_descrs(param_descrs & r) {
th_rewriter::get_param_descrs(r);
r.insert(":recover-01-max-bits", CPK_UINT, "(default: 10) maximum number of bits to consider in a clause.");
}
void operator()(goal_ref const & g,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
(*m_imp)(g, result, mc, pc, core);
}
virtual void cleanup() {
ast_manager & m = m_imp->m;
imp * d = m_imp;
#pragma omp critical (tactic_cancel)
{
d = m_imp;
}
dealloc(d);
d = alloc(imp, m, m_params);
#pragma omp critical (tactic_cancel)
{
m_imp = d;
}
}
protected:
virtual void set_cancel(bool f) {
if (m_imp)
m_imp->set_cancel(f);
}
};
tactic * mk_recover_01_tactic(ast_manager & m, params_ref const & p) {
return clean(alloc(recover_01_tactic, m, p));
}

View file

@ -0,0 +1,42 @@
/*++
Copyright (c) 2012 Microsoft Corporation
Module Name:
recover_01_tactic.h
Abstract:
Recover 01 variables
Search for clauses of the form
p or q or x = 0
~p or q or x = k1
p or ~q or x = k2
~p or ~q or x = k1+k2
Then, replaces
x with k1*y1 + k2*y2
p with y1=1
q with y2=1
where y1 and y2 are fresh 01 variables
The clauses are also removed.
Author:
Leonardo de Moura (leonardo) 2012-02-17.
Revision History:
--*/
#ifndef _RECOVER_01_TACTIC_H_
#define _RECOVER_01_TACTIC_H_
#include"params.h"
class ast_manager;
class tactic;
tactic * mk_recover_01_tactic(ast_manager & m, params_ref const & p = params_ref());
#endif

View file

@ -0,0 +1,170 @@
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
vsubst_tactic.cpp
Abstract:
Check satisfiability of QF_NRA problems using virtual subsititution quantifier-elimination.
Author:
Nikolaj (nbjorner) 2011-05-16
Notes:
Ported to tactic framework on 2012-02-28
It was qfnra_vsubst.cpp
This goal transformation checks satsifiability
of quantifier-free non-linear constraints using
virtual substitutions (applies to second-degree polynomials).
. identify non-linear variables
. use the identified variables as non-linear variables.
. give up if there are non-linear variables under uninterpreted scope.
give up if there are no non-linear variables.
. call quantifier elimination with
- non-linear elimination option.
- get-first-branch option.
. if the first branch is linear, then done.
if the result is unsat, then done.
if the first branch is non-linear then,
check candidate model,
perhaps iterate using rewriting or just give up.
. helpful facilities:
. linearize_rewriter
a*a*b + a*b = 0 <=> (b+1) = 0 \/ a = 0 \/ b = 0
. sign analysis:
a*a + b*b + c < 0 => c < 0
--*/
#include"tactic.h"
#include"qe.h"
#include"arith_decl_plugin.h"
#include"for_each_expr.h"
#include"extension_model_converter.h"
#include"params2front_end_params.h"
#include"ast_smt2_pp.h"
class vsubst_tactic : public tactic {
params_ref m_params;
class get_var_proc {
arith_util m_arith;
ptr_vector<app>& m_vars;
public:
get_var_proc(ast_manager & m, ptr_vector<app>& vars) : m_arith(m), m_vars(vars) {}
void operator()(expr* e) {
if (is_app(e)) {
app* a = to_app(e);
if (m_arith.is_real(e) &&
a->get_num_args() == 0 &&
a->get_family_id() == null_family_id) {
m_vars.push_back(a);
}
}
}
};
void get_vars(ast_manager & m, expr* fml, ptr_vector<app>& vars) {
get_var_proc proc(m, vars);
for_each_expr(proc, fml);
}
void main(goal & s, model_converter_ref & mc, params_ref const & p) {
ast_manager & m = s.m();
ptr_vector<expr> fs;
for (unsigned i = 0; i < s.size(); ++i) {
fs.push_back(s.form(i));
}
app_ref f(m.mk_and(fs.size(), fs.c_ptr()), m);
TRACE("vsubst",
s.display(tout);
tout << "goal: " << mk_ismt2_pp(f.get(), m) << "\n";);
ptr_vector<app> vars;
get_vars(m, f.get(), vars);
if (vars.empty()) {
TRACE("vsubst", tout << "no real variables\n";);
throw tactic_exception("there are no real variables");
}
front_end_params params;
params2front_end_params(p, params);
params.m_model = false;
flet<bool> fl1(params.m_nlquant_elim, true);
flet<bool> fl2(params.m_nl_arith_gb, false);
TRACE("quant_elim", tout << "Produce models: " << params.m_model << "\n";);
qe::expr_quant_elim_star1 qelim(m, params);
expr_ref g(f, m);
qe::def_vector defs(m);
lbool is_sat = qelim.first_elim(vars.size(), vars.c_ptr(), g, defs);
if (is_sat == l_undef) {
TRACE("vsubst", tout << mk_ismt2_pp(g, m) << "\n";);
throw tactic_exception("elimination was not successful");
}
if (!defs.empty()) {
extension_model_converter * ev = alloc(extension_model_converter, m);
mc = ev;
for (unsigned i = defs.size(); i > 0; ) {
--i;
ev->insert(defs.var(i), defs.def(i));
}
}
s.reset();
// TBD: wasteful as we already know it is sat or unsat.
// TBD: extract model from virtual substitution.
s.assert_expr(g);
TRACE("qfnra_vsubst",
tout << "v-subst result:\n";
s.display(tout););
}
public:
vsubst_tactic(params_ref const & p):m_params(p) {}
virtual tactic * translate(ast_manager & m) {
return alloc(vsubst_tactic, m_params);
}
virtual ~vsubst_tactic() {}
virtual void updt_params(params_ref const & p) {
m_params = p;
}
/**
\brief Check satisfiability of an assertion set of QF_NRA
by using virtual substitutions.
*/
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());
fail_if_proof_generation("vsubst", g);
fail_if_unsat_core_generation("vsubst", g);
fail_if_model_generation("vsubst", g); // disable for now due to problems with infinitesimals.
mc = 0; pc = 0; core = 0; result.reset();
main(*(g.get()), mc, m_params);
result.push_back(g.get());
SASSERT(g->is_well_sorted());
}
virtual void cleanup(void) {}
};
tactic * mk_vsubst_tactic(ast_manager & m, params_ref const & p) {
return alloc(vsubst_tactic, p);
}

View file

@ -0,0 +1,30 @@
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
vsubst_tactic.h
Abstract:
Check satisfiability of QF_NRA problems using virtual subsititution quantifier-elimination.
Author:
Nikolaj (nbjorner) 2011-05-16
Notes:
--*/
#ifndef _VSUBST_TACTIC_H_
#define _VSUBST_TACTIC_H_
#include"params.h"
class ast_manager;
class tactic;
tactic * mk_vsubst_tactic(ast_manager & m, params_ref const & p = params_ref());
#endif

View file

@ -0,0 +1,555 @@
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
ctx_simplify_tactic.cpp
Abstract:
Simple context simplifier for propagating constants.
Author:
Leonardo (leonardo) 2011-10-26
Notes:
--*/
#include"ctx_simplify_tactic.h"
#include"mk_simplified_app.h"
#include"num_occurs_goal.h"
#include"cooperate.h"
#include"ast_ll_pp.h"
#include"ast_smt2_pp.h"
struct ctx_simplify_tactic::imp {
struct cached_result {
expr * m_to;
unsigned m_lvl;
cached_result * m_next;
cached_result(expr * t, unsigned lvl, cached_result * next):
m_to(t),
m_lvl(lvl),
m_next(next) {
}
};
struct cache_cell {
expr * m_from;
cached_result * m_result;
cache_cell():m_from(0), m_result(0) {}
};
ast_manager & m;
small_object_allocator m_allocator;
obj_map<expr, expr*> m_assertions;
ptr_vector<expr> m_trail;
svector<unsigned> m_scopes;
svector<cache_cell> m_cache;
vector<ptr_vector<expr> > m_cache_undo;
unsigned m_scope_lvl;
unsigned m_depth;
unsigned m_num_steps;
num_occurs_goal m_occs;
mk_simplified_app m_mk_app;
unsigned long long m_max_memory;
unsigned m_max_depth;
unsigned m_max_steps;
bool m_bail_on_blowup;
volatile bool m_cancel;
imp(ast_manager & _m, params_ref const & p):
m(_m),
m_allocator("context-simplifier"),
m_occs(true, true),
m_mk_app(m, p) {
m_cancel = false;
m_scope_lvl = 0;
updt_params(p);
}
void set_cancel(bool f) {
m_cancel = f;
}
~imp() {
pop(m_scope_lvl);
SASSERT(m_scope_lvl == 0);
restore_cache(0);
DEBUG_CODE({
for (unsigned i = 0; i < m_cache.size(); i++) {
CTRACE("ctx_simplify_tactic_bug", m_cache[i].m_from,
tout << "i: " << i << "\n" << mk_ismt2_pp(m_cache[i].m_from, m) << "\n";
tout << "m_result: " << m_cache[i].m_result << "\n";
if (m_cache[i].m_result) tout << "lvl: " << m_cache[i].m_result->m_lvl << "\n";);
SASSERT(m_cache[i].m_from == 0);
SASSERT(m_cache[i].m_result == 0);
}
});
}
void updt_params(params_ref const & p) {
m_max_memory = megabytes_to_bytes(p.get_uint(":max-memory", UINT_MAX));
m_max_steps = p.get_uint(":max-steps", UINT_MAX);
m_max_depth = p.get_uint(":max-depth", 1024);
m_bail_on_blowup = p.get_bool(":bail-on-blowup", false);
}
void checkpoint() {
cooperate("ctx_simplify_tactic");
if (memory::get_allocation_size() > m_max_memory)
throw tactic_exception(TACTIC_MAX_MEMORY_MSG);
if (m_cancel)
throw tactic_exception(TACTIC_CANCELED_MSG);
}
bool shared(expr * t) const {
return t->get_ref_count() > 1 && m_occs.get_num_occs(t) > 1;
}
bool check_cache() {
for (unsigned i = 0; i < m_cache.size(); i++) {
cache_cell & cell = m_cache[i];
if (cell.m_from != 0) {
SASSERT(cell.m_result != 0);
cached_result * curr = cell.m_result;
while (curr) {
SASSERT(curr->m_lvl <= scope_level());
curr = curr->m_next;
}
}
}
return true;
}
void cache_core(expr * from, expr * to) {
TRACE("ctx_simplify_tactic_cache", tout << "caching\n" << mk_ismt2_pp(from, m) << "\n--->\n" << mk_ismt2_pp(to, m) << "\n";);
unsigned id = from->get_id();
m_cache.reserve(id+1);
cache_cell & cell = m_cache[id];
void * mem = m_allocator.allocate(sizeof(cached_result));
if (cell.m_from == 0) {
// new_entry
cell.m_from = from;
cell.m_result = new (mem) cached_result(to, m_scope_lvl, 0);
m.inc_ref(from);
m.inc_ref(to);
}
else {
// update
cell.m_result = new (mem) cached_result(to, m_scope_lvl, cell.m_result);
m.inc_ref(to);
}
m_cache_undo.reserve(m_scope_lvl+1);
m_cache_undo[m_scope_lvl].push_back(from);
}
void cache(expr * from, expr * to) {
if (shared(from))
cache_core(from, to);
}
unsigned scope_level() const {
return m_scope_lvl;
}
void push() {
m_scope_lvl++;
m_scopes.push_back(m_trail.size());
}
void restore_cache(unsigned lvl) {
if (lvl >= m_cache_undo.size())
return;
ptr_vector<expr> & keys = m_cache_undo[lvl];
ptr_vector<expr>::iterator it = keys.end();
ptr_vector<expr>::iterator begin = keys.begin();
while (it != begin) {
--it;
expr * key = *it;
unsigned key_id = key->get_id();
cache_cell & cell = m_cache[key_id];
SASSERT(cell.m_from == key);
SASSERT(cell.m_result != 0);
m.dec_ref(cell.m_result->m_to);
cached_result * to_delete = cell.m_result;
SASSERT(to_delete->m_lvl == lvl);
TRACE("ctx_simplify_tactic_cache", tout << "uncaching: " << to_delete->m_lvl << "\n" <<
mk_ismt2_pp(key, m) << "\n--->\n" << mk_ismt2_pp(to_delete->m_to, m) << "\nrestoring:\n";
if (to_delete->m_next) tout << mk_ismt2_pp(to_delete->m_next->m_to, m); else tout << "<null>";
tout << "\n";);
cell.m_result = to_delete->m_next;
if (cell.m_result == 0) {
m.dec_ref(cell.m_from);
cell.m_from = 0;
}
m_allocator.deallocate(sizeof(cached_result), to_delete);
}
keys.reset();
}
void pop(unsigned num_scopes) {
if (num_scopes == 0)
return;
SASSERT(num_scopes <= m_scope_lvl);
SASSERT(m_scope_lvl == m_scopes.size());
// undo assertions
unsigned old_trail_size = m_scopes[m_scope_lvl - num_scopes];
unsigned i = m_trail.size();
while (i > old_trail_size) {
--i;
expr * key = m_trail.back();
m_assertions.erase(key);
m_trail.pop_back();
}
SASSERT(m_trail.size() == old_trail_size);
m_scopes.shrink(m_scope_lvl - num_scopes);
// restore cache
for (unsigned i = 0; i < num_scopes; i++) {
restore_cache(m_scope_lvl);
m_scope_lvl--;
}
CASSERT("ctx_simplify_tactic", check_cache());
}
void assert_eq_core(expr * t, app * val) {
if (m_assertions.contains(t)) {
// This branch can only happen when m_max_depth was reached.
// It can happen when m_assertions contains an entry t->val',
// but (= t val) was not simplified to (= val' val)
// because the simplifier stopped at depth m_max_depth
return;
}
CTRACE("assert_eq_bug", m_assertions.contains(t), tout << "m_depth: " << m_depth << " m_max_depth: " << m_max_depth << "\n"
<< "t:\n" << mk_ismt2_pp(t, m) << "\nval:\n" << mk_ismt2_pp(val, m) << "\n";
expr * old_val = 0;
m_assertions.find(t, old_val);
tout << "old_val:\n" << mk_ismt2_pp(old_val, m) << "\n";);
m_assertions.insert(t, val);
m_trail.push_back(t);
}
void assert_eq_val(expr * t, app * val, bool mk_scope) {
if (shared(t)) {
if (mk_scope)
push();
assert_eq_core(t, val);
}
}
void assert_expr(expr * t, bool sign) {
if (m.is_not(t)) {
t = to_app(t)->get_arg(0);
sign = !sign;
}
bool mk_scope = true;
if (shared(t)) {
push();
mk_scope = false;
assert_eq_core(t, sign ? m.mk_false() : m.mk_true());
}
expr * lhs, * rhs;
if (!sign && m.is_eq(t, lhs, rhs)) {
if (m.is_value(rhs))
assert_eq_val(lhs, to_app(rhs), mk_scope);
else if (m.is_value(lhs))
assert_eq_val(rhs, to_app(lhs), mk_scope);
}
}
bool is_cached(expr * t, expr_ref & r) {
unsigned id = t->get_id();
if (id >= m_cache.size())
return false;
cache_cell & cell = m_cache[id];
SASSERT(cell.m_result == 0 || cell.m_result->m_lvl <= scope_level());
if (cell.m_result != 0 && cell.m_result->m_lvl == scope_level()) {
SASSERT(cell.m_from == t);
SASSERT(cell.m_result->m_to != 0);
r = cell.m_result->m_to;
return true;
}
return false;
}
void simplify(expr * t, expr_ref & r) {
r = 0;
if (m_depth >= m_max_depth || m_num_steps >= m_max_steps || !is_app(t)) {
r = t;
return;
}
checkpoint();
TRACE("ctx_simplify_tactic_detail", tout << "processing: " << mk_bounded_pp(t, m) << "\n";);
expr * _r;
if (m_assertions.find(t, _r)) {
r = _r;
SASSERT(r.get() != 0);
return;
}
if (is_cached(t, r)) {
SASSERT(r.get() != 0);
return;
}
m_num_steps++;
m_depth++;
if (m.is_or(t))
simplify_or_and<true>(to_app(t), r);
else if (m.is_and(t))
simplify_or_and<false>(to_app(t), r);
else if (m.is_ite(t))
simplify_ite(to_app(t), r);
else
simplify_app(to_app(t), r);
m_depth--;
SASSERT(r.get() != 0);
TRACE("ctx_simplify_tactic_detail", tout << "result:\n" << mk_bounded_pp(t, m) << "\n---->\n" << mk_bounded_pp(r, m) << "\n";);
}
template<bool OR>
void simplify_or_and(app * t, expr_ref & r) {
// go forwards
expr_ref_buffer new_args(m);
unsigned old_lvl = scope_level();
bool modified = false;
unsigned num_args = t->get_num_args();
for (unsigned i = 0; i < num_args; i++) {
expr * arg = t->get_arg(i);
expr_ref new_arg(m);
simplify(arg, new_arg);
if (new_arg != arg)
modified = true;
if ((OR && m.is_false(new_arg)) ||
(!OR && m.is_true(new_arg))) {
modified = true;
continue;
}
if ((OR && m.is_true(new_arg)) ||
(!OR && m.is_false(new_arg))) {
r = new_arg;
pop(scope_level() - old_lvl);
cache(t, r);
return;
}
new_args.push_back(new_arg);
if (i < num_args - 1)
assert_expr(new_arg, OR);
}
pop(scope_level() - old_lvl);
// go backwards
expr_ref_buffer new_new_args(m);
unsigned i = new_args.size();
while (i > 0) {
--i;
expr * arg = new_args[i];
expr_ref new_arg(m);
simplify(arg, new_arg);
if (new_arg != arg)
modified = true;
if ((OR && m.is_false(new_arg)) ||
(!OR && m.is_true(new_arg))) {
modified = true;
continue;
}
if ((OR && m.is_true(new_arg)) ||
(!OR && m.is_false(new_arg))) {
r = new_arg;
pop(scope_level() - old_lvl);
cache(t, r);
return;
}
new_new_args.push_back(new_arg);
if (i > 0)
assert_expr(new_arg, OR);
}
pop(scope_level() - old_lvl);
if (!modified) {
r = t;
}
else {
std::reverse(new_new_args.c_ptr(), new_new_args.c_ptr() + new_new_args.size());
m_mk_app(t->get_decl(), new_new_args.size(), new_new_args.c_ptr(), r);
}
cache(t, r);
}
void simplify_ite(app * ite, expr_ref & r) {
expr * c = ite->get_arg(0);
expr * t = ite->get_arg(1);
expr * e = ite->get_arg(2);
expr_ref new_c(m);
unsigned old_lvl = scope_level();
simplify(c, new_c);
if (m.is_true(new_c)) {
simplify(t, r);
}
else if (m.is_false(new_c)) {
simplify(e, r);
}
else {
expr_ref new_t(m);
expr_ref new_e(m);
assert_expr(new_c, false);
simplify(t, new_t);
pop(scope_level() - old_lvl);
assert_expr(new_c, true);
simplify(e, new_e);
pop(scope_level() - old_lvl);
if (c == new_c && t == new_t && e == new_e) {
r = ite;
}
else {
expr * args[3] = { new_c.get(), new_t.get(), new_e.get() };
TRACE("ctx_simplify_tactic_ite_bug",
tout << "mk_ite\n" << mk_ismt2_pp(new_c.get(), m) << "\n" << mk_ismt2_pp(new_t.get(), m)
<< "\n" << mk_ismt2_pp(new_e.get(), m) << "\n";);
m_mk_app(ite->get_decl(), 3, args, r);
}
}
cache(ite, r);
}
void simplify_app(app * t, expr_ref & r) {
if (t->get_num_args() == 0) {
r = t;
return;
}
expr_ref_buffer new_args(m);
bool modified = false;
unsigned num_args = t->get_num_args();
for (unsigned i = 0; i < num_args; i++) {
expr * arg = t->get_arg(i);
expr_ref new_arg(m);
simplify(arg, new_arg);
CTRACE("ctx_simplify_tactic_bug", new_arg.get() == 0, tout << mk_ismt2_pp(arg, m) << "\n";);
SASSERT(new_arg);
if (new_arg != arg)
modified = true;
new_args.push_back(new_arg);
}
if (!modified) {
r = t;
}
else {
m_mk_app(t->get_decl(), new_args.size(), new_args.c_ptr(), r);
}
}
unsigned expr_size(expr* s) {
ast_mark visit;
unsigned sz = 0;
ptr_vector<expr> todo;
todo.push_back(s);
while (!todo.empty()) {
s = todo.back();
todo.pop_back();
if (visit.is_marked(s)) {
continue;
}
visit.mark(s, true);
++sz;
for (unsigned i = 0; is_app(s) && i < to_app(s)->get_num_args(); ++i) {
todo.push_back(to_app(s)->get_arg(i));
}
}
return sz;
}
void process(expr * s, expr_ref & r) {
TRACE("ctx_simplify_tactic", tout << "simplifying:\n" << mk_ismt2_pp(s, m) << "\n";);
SASSERT(m_scope_lvl == 0);
m_depth = 0;
simplify(s, r);
SASSERT(m_scope_lvl == 0);
SASSERT(m_depth == 0);
SASSERT(r.get() != 0);
TRACE("ctx_simplify_tactic", tout << "result\n" << mk_ismt2_pp(r, m) << " :num-steps " << m_num_steps << "\n";
tout << "old size: " << expr_size(s) << " new size: " << expr_size(r) << "\n";);
if (m_bail_on_blowup && expr_size(s) < expr_size(r)) {
r = s;
}
}
void operator()(goal & g) {
SASSERT(g.is_well_sorted());
bool proofs_enabled = g.proofs_enabled();
m_occs.reset();
m_occs(g);
m_num_steps = 0;
expr_ref r(m);
proof * new_pr = 0;
tactic_report report("ctx-simplify", g);
unsigned sz = g.size();
for (unsigned i = 0; i < sz; i++) {
if (g.inconsistent())
return;
expr * t = g.form(i);
process(t, r);
if (proofs_enabled) {
proof * pr = g.pr(i);
new_pr = m.mk_modus_ponens(pr, m.mk_rewrite_star(t, r, 0, 0)); // TODO :-)
}
g.update(i, r, new_pr, g.dep(i));
}
IF_VERBOSE(TACTIC_VERBOSITY_LVL, verbose_stream() << "(ctx-simplify :num-steps " << m_num_steps << ")\n";);
SASSERT(g.is_well_sorted());
}
};
ctx_simplify_tactic::ctx_simplify_tactic(ast_manager & m, params_ref const & p):
m_imp(alloc(imp, m, p)),
m_params(p) {
}
ctx_simplify_tactic::~ctx_simplify_tactic() {
dealloc(m_imp);
}
void ctx_simplify_tactic::updt_params(params_ref const & p) {
m_params = p;
m_imp->updt_params(p);
}
void ctx_simplify_tactic::get_param_descrs(param_descrs & r) {
insert_max_memory(r);
insert_max_steps(r);
r.insert(":max-depth", CPK_UINT, "(default: 1024) maximum term depth.");
}
void ctx_simplify_tactic::operator()(goal_ref const & in,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
mc = 0; pc = 0; core = 0;
(*m_imp)(*(in.get()));
in->inc_depth();
result.push_back(in.get());
}
void ctx_simplify_tactic::set_cancel(bool f) {
if (m_imp)
m_imp->set_cancel(f);
}
void ctx_simplify_tactic::cleanup() {
ast_manager & m = m_imp->m;
imp * d = m_imp;
#pragma omp critical (tactic_cancel)
{
m_imp = 0;
}
dealloc(d);
d = alloc(imp, m, m_params);
#pragma omp critical (tactic_cancel)
{
m_imp = d;
}
}

View file

@ -0,0 +1,56 @@
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
ctx_simplify_tactic.h
Abstract:
Simple context simplifier for propagating constants.
Author:
Leonardo (leonardo) 2011-10-26
Notes:
--*/
#ifndef _CTX_SIMPLIFY_TACTIC_H_
#define _CTX_SIMPLIFY_TACTIC_H_
#include"tactical.h"
class ctx_simplify_tactic : public tactic {
struct imp;
imp * m_imp;
params_ref m_params;
public:
ctx_simplify_tactic(ast_manager & m, params_ref const & p = params_ref());
virtual tactic * translate(ast_manager & m) {
return alloc(ctx_simplify_tactic, m, m_params);
}
virtual ~ctx_simplify_tactic();
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()(goal_ref const & in,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core);
virtual void cleanup();
protected:
virtual void set_cancel(bool f);
};
inline tactic * mk_ctx_simplify_tactic(ast_manager & m, params_ref const & p = params_ref()) {
return clean(alloc(ctx_simplify_tactic, m, p));
}
#endif

View file

@ -0,0 +1,149 @@
/*++
Copyright (c) 2012 Microsoft Corporation
Module Name:
distribute_forall_tactic.cpp
Abstract:
<abstract>
Author:
Leonardo de Moura (leonardo) 2012-02-18.
--*/
#include"tactical.h"
#include"rewriter_def.h"
#include"var_subst.h"
class distribute_forall_tactic : public tactic {
struct rw_cfg : public default_rewriter_cfg {
ast_manager & m;
rw_cfg(ast_manager & _m):m(_m) {}
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) {
if (m.is_not(new_body) && m.is_or(to_app(new_body)->get_arg(0))) {
// (forall X (not (or F1 ... Fn)))
// -->
// (and (forall X (not F1))
// ...
// (forall X (not Fn)))
app * or_e = to_app(to_app(new_body)->get_arg(0));
unsigned num_args = or_e->get_num_args();
expr_ref_buffer new_args(m);
for (unsigned i = 0; i < num_args; i++) {
expr * arg = or_e->get_arg(i);
expr * not_arg = m.mk_not(arg);
quantifier_ref tmp_q(m);
tmp_q = m.update_quantifier(old_q, not_arg);
expr_ref new_q(m);
elim_unused_vars(m, tmp_q, new_q);
new_args.push_back(new_q);
}
result = m.mk_and(new_args.size(), new_args.c_ptr());
return true;
}
if (m.is_and(new_body)) {
// (forall X (and F1 ... Fn))
// -->
// (and (forall X F1)
// ...
// (forall X Fn)
unsigned num_args = to_app(new_body)->get_num_args();
expr_ref_buffer new_args(m);
for (unsigned i = 0; i < num_args; i++) {
expr * arg = to_app(new_body)->get_arg(i);
quantifier_ref tmp_q(m);
tmp_q = m.update_quantifier(old_q, arg);
expr_ref new_q(m);
elim_unused_vars(m, tmp_q, new_q);
new_args.push_back(new_q);
}
result = m.mk_and(new_args.size(), new_args.c_ptr());
return true;
}
return false;
}
};
struct rw : public rewriter_tpl<rw_cfg> {
rw_cfg m_cfg;
rw(ast_manager & m, bool proofs_enabled):
rewriter_tpl<rw_cfg>(m, proofs_enabled, m_cfg),
m_cfg(m) {
}
};
rw * m_rw;
public:
distribute_forall_tactic():m_rw(0) {}
virtual tactic * translate(ast_manager & m) {
return alloc(distribute_forall_tactic);
}
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());
ast_manager & m = g->m();
bool produce_proofs = g->proofs_enabled();
rw r(m, produce_proofs);
#pragma omp critical (tactic_cancel)
{
m_rw = &r;
}
mc = 0; pc = 0; core = 0; result.reset();
tactic_report report("distribute-forall", *g);
expr_ref new_curr(m);
proof_ref new_pr(m);
unsigned size = g->size();
for (unsigned idx = 0; idx < size; idx++) {
if (g->inconsistent())
break;
expr * curr = g->form(idx);
r(curr, new_curr, new_pr);
if (g->proofs_enabled()) {
proof * pr = g->pr(idx);
new_pr = m.mk_modus_ponens(pr, new_pr);
}
g->update(idx, new_curr, new_pr, g->dep(idx));
}
g->inc_depth();
result.push_back(g.get());
TRACE("distribute-forall", g->display(tout););
SASSERT(g->is_well_sorted());
#pragma omp critical (tactic_cancel)
{
m_rw = 0;
}
}
virtual void set_cancel(bool f) {
if (m_rw)
m_rw->set_cancel(f);
}
virtual void cleanup() {}
};
tactic * mk_distribute_forall_tactic(ast_manager & m, params_ref const & p) {
return alloc(distribute_forall_tactic);
}

View file

@ -0,0 +1,26 @@
/*++
Copyright (c) 2012 Microsoft Corporation
Module Name:
distribute_forall_tactic.h
Abstract:
<abstract>
Author:
Leonardo de Moura (leonardo) 2012-02-18.
--*/
#ifndef _DISTRIBUTE_FORALL_TACTIC_H_
#define _DISTRIBUTE_FORALL_TACTIC_H_
#include"params.h"
class ast_manager;
class tactic;
tactic * mk_distribute_forall_tactic(ast_manager & m, params_ref const & p);
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,30 @@
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
elim_uncnstr_tactic.h
Abstract:
Eliminated applications containing unconstrained variables.
Author:
Leonardo (leonardo) 2011-10-22
Notes:
--*/
#ifndef _ELIM_UNCNSTR_TACTIC_H_
#define _ELIM_UNCNSTR_TACTIC_H_
#include"params.h"
class tactic;
class ast_manager;
tactic * mk_elim_uncnstr_tactic(ast_manager & m, params_ref const & p = params_ref());
#endif

View file

@ -0,0 +1,126 @@
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
nnf_tactic.cpp
Abstract:
NNF tactic
Author:
Leonardo de Moura (leonardo) 2011-12-28.
Revision History:
--*/
#include"nnf.h"
#include"tactical.h"
class nnf_tactic : public tactic {
params_ref m_params;
nnf * m_nnf;
struct set_nnf {
nnf_tactic & m_owner;
set_nnf(nnf_tactic & owner, nnf & n):
m_owner(owner) {
#pragma omp critical (nnf_tactic)
{
m_owner.m_nnf = &n;
}
}
~set_nnf() {
#pragma omp critical (nnf_tactic)
{
m_owner.m_nnf = 0;
}
}
};
public:
nnf_tactic(params_ref const & p):
m_params(p),
m_nnf(0) {
TRACE("nnf", tout << "nnf_tactic constructor: " << p << "\n";);
}
virtual tactic * translate(ast_manager & m) {
return alloc(nnf_tactic, m_params);
}
virtual ~nnf_tactic() {}
virtual void updt_params(params_ref const & p) { m_params = p; }
virtual void collect_param_descrs(param_descrs & r) { nnf::get_param_descrs(r); }
virtual void operator()(goal_ref const & g,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
TRACE("nnf", tout << "params: " << m_params << "\n"; g->display(tout););
SASSERT(g->is_well_sorted());
mc = 0; pc = 0; core = 0;
tactic_report report("nnf", *g);
bool produce_proofs = g->proofs_enabled();
ast_manager & m = g->m();
defined_names dnames(m);
nnf local_nnf(m, dnames, m_params);
set_nnf setter(*this, local_nnf);
expr_ref_vector defs(m);
proof_ref_vector def_prs(m);
expr_ref new_curr(m);
proof_ref new_pr(m);
unsigned sz = g->size();
for (unsigned i = 0; i < sz; i++) {
expr * curr = g->form(i);
local_nnf(curr, defs, def_prs, new_curr, new_pr);
if (produce_proofs) {
proof * pr = g->pr(i);
new_pr = m.mk_modus_ponens(pr, new_pr);
}
g->update(i, new_curr, new_pr, g->dep(i));
}
sz = defs.size();
for (unsigned i = 0; i < sz; i++) {
if (produce_proofs)
g->assert_expr(defs.get(i), def_prs.get(i), 0);
else
g->assert_expr(defs.get(i), 0, 0);
}
g->inc_depth();
result.push_back(g.get());
TRACE("nnf", g->display(tout););
SASSERT(g->is_well_sorted());
}
virtual void cleanup() {}
virtual void set_cancel(bool f) {
#pragma omp critical (nnf_tactic)
{
if (m_nnf)
m_nnf->set_cancel(f);
}
}
};
tactic * mk_snf_tactic(ast_manager & m, params_ref const & p) {
return alloc(nnf_tactic, p);
}
tactic * mk_nnf_tactic(ast_manager & m, params_ref const & p) {
params_ref new_p(p);
new_p.set_sym(":nnf-mode", symbol("full"));
TRACE("nnf", tout << "mk_nnf: " << new_p << "\n";);
return using_params(mk_snf_tactic(m, p), new_p);
}

View file

@ -0,0 +1,30 @@
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
nnf_tactic.h
Abstract:
NNF tactic
Author:
Leonardo de Moura (leonardo) 2011-12-28.
Revision History:
--*/
#ifndef _NNF_TACTIC_H_
#define _NNF_TACTIC_H_
#include"params.h"
class ast_manager;
class tactic;
tactic * mk_snf_tactic(ast_manager & m, params_ref const & p = params_ref());
tactic * mk_nnf_tactic(ast_manager & m, params_ref const & p = params_ref());
#endif

View file

@ -0,0 +1,252 @@
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
occf_tactic.cpp
Abstract:
Put clauses in the assertion set in
OOC (one constraint per clause) form.
Constraints occuring in formulas that
are not clauses are ignored.
The formula can be put into CNF by
using mk_sat_preprocessor strategy.
Author:
Leonardo de Moura (leonardo) 2011-12-28.
Revision History:
--*/
#include"tactical.h"
#include"occf_tactic.h"
#include"filter_model_converter.h"
#include"cooperate.h"
class occf_tactic : public tactic {
struct imp {
ast_manager & m;
volatile bool m_cancel;
filter_model_converter * m_mc;
imp(ast_manager & _m):
m(_m) {
m_cancel = false;
}
void set_cancel(bool f) {
m_cancel = f;
}
void checkpoint() {
if (m_cancel)
throw tactic_exception(TACTIC_CANCELED_MSG);
cooperate("occf");
}
bool is_literal(expr * t) const {
expr * atom;
return is_uninterp_const(t) || (m.is_not(t, atom) && is_uninterp_const(atom));
}
bool is_constraint(expr * t) const {
return !is_literal(t);
}
bool is_target(app * cls) {
SASSERT(m.is_or(cls));
bool found = false;
unsigned num = cls->get_num_args();
for (unsigned i = 0; i < num; i++) {
if (is_constraint(cls->get_arg(i))) {
if (found)
return true;
found = true;
}
}
return false;
}
struct bvar_info {
expr * m_bvar;
unsigned m_gen_pos:1;
unsigned m_gen_neg:1;
bvar_info():m_bvar(0), m_gen_pos(false), m_gen_neg(false) {}
bvar_info(expr * var, bool sign):
m_bvar(var),
m_gen_pos(!sign),
m_gen_neg(sign) {
}
};
typedef obj_map<expr, bvar_info> cnstr2bvar;
expr * get_aux_lit(cnstr2bvar & c2b, expr * cnstr, goal_ref const & g) {
bool sign = false;
while (m.is_not(cnstr)) {
cnstr = to_app(cnstr)->get_arg(0);
sign = !sign;
}
cnstr2bvar::obj_map_entry * entry = c2b.find_core(cnstr);
if (entry == 0)
return 0;
bvar_info & info = entry->get_data().m_value;
if (sign) {
if (!info.m_gen_neg) {
info.m_gen_neg = true;
g->assert_expr(m.mk_or(info.m_bvar, m.mk_not(cnstr)), 0, 0);
}
return m.mk_not(info.m_bvar);
}
else {
if (!info.m_gen_pos) {
info.m_gen_pos = true;
g->assert_expr(m.mk_or(m.mk_not(info.m_bvar), cnstr), 0, 0);
}
return info.m_bvar;
}
}
expr * mk_aux_lit(cnstr2bvar & c2b, expr * cnstr, bool produce_models, goal_ref const & g) {
bool sign = false;
while (m.is_not(cnstr)) {
cnstr = to_app(cnstr)->get_arg(0);
sign = !sign;
}
SASSERT(!c2b.contains(cnstr));
expr * bvar = m.mk_fresh_const(0, m.mk_bool_sort());
if (produce_models)
m_mc->insert(to_app(bvar)->get_decl());
c2b.insert(cnstr, bvar_info(bvar, sign));
if (sign) {
g->assert_expr(m.mk_or(bvar, m.mk_not(cnstr)), 0, 0);
return m.mk_not(bvar);
}
else {
g->assert_expr(m.mk_or(m.mk_not(bvar), cnstr), 0, 0);
return bvar;
}
}
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());
mc = 0; pc = 0; core = 0;
fail_if_proof_generation("occf", g);
bool produce_models = g->models_enabled();
tactic_report report("occf", *g);
m_mc = 0;
ptr_vector<expr> new_lits;
cnstr2bvar c2b;
unsigned sz = g->size();
for (unsigned i = 0; i < sz; i++) {
checkpoint();
expr * f = g->form(i);
expr_dependency * d = g->dep(i);
if (!m.is_or(f))
continue;
app * cls = to_app(f);
if (!is_target(cls))
continue;
if (produce_models && !m_mc) {
m_mc = alloc(filter_model_converter, m);
mc = m_mc;
}
expr * keep = 0;
new_lits.reset();
unsigned num = cls->get_num_args();
for (unsigned j = 0; j < num; j++) {
expr * l = cls->get_arg(j);
if (is_constraint(l)) {
expr * new_l = get_aux_lit(c2b, l, g);
if (new_l != 0) {
new_lits.push_back(new_l);
}
else if (keep == 0) {
keep = l;
}
else {
new_l = mk_aux_lit(c2b, l, produce_models, g);
new_lits.push_back(new_l);
}
}
else {
new_lits.push_back(l);
}
}
if (keep != 0)
new_lits.push_back(keep);
g->update(i, m.mk_or(new_lits.size(), new_lits.c_ptr()), 0, d);
}
g->inc_depth();
result.push_back(g.get());
TRACE("occf", g->display(tout););
SASSERT(g->is_well_sorted());
}
};
imp * m_imp;
public:
occf_tactic(ast_manager & m) {
m_imp = alloc(imp, m);
}
virtual tactic * translate(ast_manager & m) {
return alloc(occf_tactic, m);
}
virtual ~occf_tactic() {
dealloc(m_imp);
}
virtual void updt_params(params_ref const & p) {}
virtual void collect_param_descrs(param_descrs & r) {}
virtual void operator()(goal_ref const & in,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
(*m_imp)(in, result, mc, pc, core);
}
virtual void cleanup() {
ast_manager & m = m_imp->m;
imp * d = m_imp;
#pragma omp critical (tactic_cancel)
{
m_imp = 0;
}
dealloc(d);
d = alloc(imp, m);
#pragma omp critical (tactic_cancel)
{
m_imp = d;
}
}
protected:
virtual void set_cancel(bool f) {
if (m_imp)
m_imp->set_cancel(f);
}
};
tactic * mk_occf_tactic(ast_manager & m, params_ref const & p) {
return clean(alloc(occf_tactic, m));
}

View file

@ -0,0 +1,34 @@
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
occf_tactic.h
Abstract:
Put clauses in the assertion set in
OOC (one constraint per clause) form.
Constraints occuring in formulas that
are not clauses are ignored.
The formula can be put into CNF by
using mk_sat_preprocessor strategy.
Author:
Leonardo de Moura (leonardo) 2011-12-28.
Revision History:
--*/
#ifndef _OCCF_TACTIC_H_
#define _OCCF_TACTIC_H_
#include"params.h"
class ast_manager;
class tactic;
tactic * mk_occf_tactic(ast_manager & m, params_ref const & p = params_ref());
#endif

View file

@ -0,0 +1,275 @@
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
propagate_values_tactic.cpp
Abstract:
Propagate values using equalities of the form (= t v) where v is a value,
and atoms t and (not t)
Author:
Leonardo de Moura (leonardo) 2011-12-28.
Revision History:
--*/
#include"tactical.h"
#include"propagate_values_tactic.h"
#include"th_rewriter.h"
#include"ast_smt2_pp.h"
#include"expr_substitution.h"
#include"goal_shared_occs.h"
class propagate_values_tactic : public tactic {
struct imp {
ast_manager & m_manager;
th_rewriter m_r;
scoped_ptr<expr_substitution> m_subst;
goal * m_goal;
goal_shared_occs m_occs;
unsigned m_idx;
unsigned m_max_rounds;
bool m_modified;
imp(ast_manager & m, params_ref const & p):
m_manager(m),
m_r(m, p),
m_goal(0),
m_occs(m, true /* track atoms */) {
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);
}
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;
}
void push_result(expr * new_curr, proof * new_pr) {
if (m_goal->proofs_enabled()) {
proof * pr = m_goal->pr(m_idx);
new_pr = m().mk_modus_ponens(pr, new_pr);
}
expr_dependency_ref new_d(m());
if (m_goal->unsat_core_enabled()) {
new_d = m_goal->dep(m_idx);
expr_dependency * used_d = m_r.get_used_dependencies();
if (used_d != 0) {
new_d = m().mk_join(new_d, used_d);
m_r.reset_used_dependencies();
}
}
m_goal->update(m_idx, new_curr, new_pr, new_d);
if (is_shared(new_curr)) {
m_subst->insert(new_curr, m().mk_true(), m().mk_iff_true(new_pr), new_d);
}
expr * atom;
if (is_shared_neg(new_curr, atom)) {
m_subst->insert(atom, m().mk_false(), m().mk_iff_false(new_pr), new_d);
}
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, new_d);
}
}
void process_current() {
expr * curr = m_goal->form(m_idx);
expr_ref new_curr(m());
proof_ref new_pr(m());
if (!m_subst->empty()) {
m_r(curr, new_curr, new_pr);
}
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()(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());
mc = 0; pc = 0; core = 0;
tactic_report report("propagate-values", *g);
m_goal = g.get();
bool forward = true;
expr_ref new_curr(m());
proof_ref new_pr(m());
unsigned size = m_goal->size();
m_idx = 0;
m_modified = false;
unsigned round = 0;
if (m_goal->inconsistent())
goto end;
m_subst = alloc(expr_substitution, m(), g->unsat_core_enabled(), g->proofs_enabled());
m_r.set_substitution(m_subst.get());
m_occs(*m_goal);
while (true) {
TRACE("propagate_values", m_goal->display(tout););
if (forward) {
for (; m_idx < size; m_idx++) {
process_current();
if (m_goal->inconsistent())
goto end;
}
if (m_subst->empty() && !m_modified)
goto end;
m_occs(*m_goal);
m_idx = m_goal->size();
forward = false;
m_subst->reset();
m_r.set_substitution(m_subst.get()); // reset, but keep substitution
}
else {
while (m_idx > 0) {
m_idx--;
process_current();
if (m_goal->inconsistent())
goto end;
}
if (!m_modified)
goto end;
m_subst->reset();
m_r.set_substitution(m_subst.get()); // reset, but keep substitution
m_modified = false;
m_occs(*m_goal);
m_idx = 0;
size = m_goal->size();
forward = true;
}
round++;
if (round >= m_max_rounds)
break;
IF_VERBOSE(100, verbose_stream() << "starting new round, goal size: " << m_goal->num_exprs() << std::endl;);
TRACE("propgate_values", tout << "round finished\n"; m_goal->display(tout); tout << "\n";);
}
end:
m_goal->elim_redundancies();
m_goal->inc_depth();
result.push_back(m_goal);
SASSERT(m_goal->is_well_sorted());
TRACE("propagate_values", m_goal->display(tout););
m_goal = 0;
}
};
imp * m_imp;
params_ref m_params;
public:
propagate_values_tactic(ast_manager & m, params_ref const & p):
m_params(p) {
m_imp = alloc(imp, m, p);
}
virtual tactic * translate(ast_manager & m) {
return alloc(propagate_values_tactic, m, m_params);
}
virtual ~propagate_values_tactic() {
dealloc(m_imp);
}
virtual void updt_params(params_ref const & p) {
m_params = p;
m_imp->updt_params(p);
}
virtual void collect_param_descrs(param_descrs & r) {
th_rewriter::get_param_descrs(r);
r.insert(":max-rounds", CPK_UINT, "(default: 2) maximum number of rounds.");
}
virtual void operator()(goal_ref const & in,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
(*m_imp)(in, result, mc, pc, core);
}
virtual void cleanup() {
ast_manager & m = m_imp->m();
imp * d = m_imp;
#pragma omp critical (tactic_cancel)
{
m_imp = 0;
}
dealloc(d);
d = alloc(imp, m, m_params);
#pragma omp critical (tactic_cancel)
{
m_imp = d;
}
}
protected:
virtual void set_cancel(bool f) {
if (m_imp)
m_imp->set_cancel(f);
}
};
tactic * mk_propagate_values_tactic(ast_manager & m, params_ref const & p) {
return clean(alloc(propagate_values_tactic, m, p));
}

View file

@ -0,0 +1,29 @@
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
propagate_values_tactic.h
Abstract:
Propagate values using equalities of the form (= t v) where v is a value,
and atoms t and (not t)
Author:
Leonardo de Moura (leonardo) 2011-12-28.
Revision History:
--*/
#ifndef _PROPAGATE_VALUES_TACTIC_H_
#define _PROPAGATE_VALUES_TACTIC_H_
#include"params.h"
class ast_manager;
class tactic;
tactic * mk_propagate_values_tactic(ast_manager & m, params_ref const & p = params_ref());
#endif

View file

@ -0,0 +1,139 @@
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
simplify_tactic.cpp
Abstract:
Apply simplification and rewriting rules.
Author:
Leonardo (leonardo) 2011-11-20
Notes:
--*/
#include"simplify_tactic.h"
#include"th_rewriter.h"
#include"ast_smt2_pp.h"
struct simplify_tactic::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()(goal & g) {
SASSERT(g.is_well_sorted());
tactic_report report("simplifier", g);
TRACE("before_simplifier", g.display(tout););
m_num_steps = 0;
if (g.inconsistent())
return;
expr_ref new_curr(m());
proof_ref new_pr(m());
unsigned size = g.size();
for (unsigned idx = 0; idx < size; idx++) {
if (g.inconsistent())
break;
expr * curr = g.form(idx);
m_r(curr, new_curr, new_pr);
m_num_steps += m_r.get_num_steps();
if (g.proofs_enabled()) {
proof * pr = g.pr(idx);
new_pr = m().mk_modus_ponens(pr, new_pr);
}
g.update(idx, new_curr, new_pr, g.dep(idx));
}
TRACE("after_simplifier_bug", g.display(tout););
g.elim_redundancies();
TRACE("after_simplifier", g.display(tout););
TRACE("after_simplifier_detail", g.display_with_dependencies(tout););
SASSERT(g.is_well_sorted());
}
unsigned get_num_steps() const { return m_num_steps; }
};
simplify_tactic::simplify_tactic(ast_manager & m, params_ref const & p):
m_params(p) {
m_imp = alloc(imp, m, p);
}
simplify_tactic::~simplify_tactic() {
dealloc(m_imp);
}
void simplify_tactic::updt_params(params_ref const & p) {
m_params = p;
m_imp->m_r.updt_params(p);
}
void simplify_tactic::get_param_descrs(param_descrs & r) {
th_rewriter::get_param_descrs(r);
}
void simplify_tactic::operator()(goal_ref const & in,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
(*m_imp)(*(in.get()));
in->inc_depth();
result.push_back(in.get());
mc = 0; pc = 0; core = 0;
}
void simplify_tactic::set_cancel(bool f) {
if (m_imp)
m_imp->set_cancel(f);
}
void simplify_tactic::cleanup() {
ast_manager & m = m_imp->m();
imp * d = m_imp;
#pragma omp critical (tactic_cancel)
{
m_imp = 0;
}
dealloc(d);
d = alloc(imp, m, m_params);
#pragma omp critical (tactic_cancel)
{
m_imp = d;
}
}
unsigned simplify_tactic::get_num_steps() const {
return m_imp->get_num_steps();
}
tactic * mk_simplify_tactic(ast_manager & m, params_ref const & p) {
return clean(alloc(simplify_tactic, m, p));
}
tactic * mk_elim_and_tactic(ast_manager & m, params_ref const & p) {
params_ref xp = p;
xp.set_bool(":elim-and", true);
return using_params(mk_simplify_tactic(m, xp), xp);
}

View file

@ -0,0 +1,54 @@
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
simplify_tactic.h
Abstract:
Apply simplification and rewriting rules.
Author:
Leonardo (leonardo) 2011-11-20
Notes:
--*/
#ifndef _SIMPLIFY_TACTIC_H_
#define _SIMPLIFY_TACTIC_H_
#include"tactic.h"
#include"tactical.h"
class simplify_tactic : public tactic {
struct imp;
imp * m_imp;
params_ref m_params;
public:
simplify_tactic(ast_manager & m, params_ref const & ref = params_ref());
virtual ~simplify_tactic();
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()(goal_ref const & in,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core);
virtual void cleanup();
unsigned get_num_steps() const;
virtual void set_cancel(bool f);
virtual tactic * translate(ast_manager & m) { return alloc(simplify_tactic, m, m_params); }
};
tactic * mk_simplify_tactic(ast_manager & m, params_ref const & p = params_ref());
tactic * mk_elim_and_tactic(ast_manager & m, params_ref const & p = params_ref());
#endif

View file

@ -0,0 +1,791 @@
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
solve_eqs_tactic.cpp
Abstract:
Tactic for solving equations and performing gaussian elimination.
Author:
Leonardo de Moura (leonardo) 2011-12-29.
Revision History:
--*/
#include"tactical.h"
#include"expr_replacer.h"
#include"extension_model_converter.h"
#include"occurs.h"
#include"cooperate.h"
#include"goal_shared_occs.h"
#include"ast_smt2_pp.h"
class solve_eqs_tactic : public tactic {
struct imp {
typedef extension_model_converter gmc;
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_theory_solver;
bool m_ite_solver;
unsigned m_max_occs;
scoped_ptr<expr_substitution> m_subst;
scoped_ptr<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;
bool m_produce_proofs;
bool m_produce_unsat_cores;
bool m_produce_models;
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_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; }
void updt_params(params_ref const & p) {
m_ite_solver = p.get_bool(":ite-solver", true);
m_theory_solver = p.get_bool(":theory-solver", true);
m_max_occs = p.get_uint(":solve-eqs-max-occs", UINT_MAX);
}
void set_cancel(bool f) {
m_cancel = f;
m_r->set_cancel(f);
}
void checkpoint() {
if (m_cancel)
throw tactic_exception(TACTIC_CANCELED_MSG);
cooperate("solve-eqs");
}
// Check if the number of occurrences of t is below the specified threshold :solve-eqs-max-occs
bool check_occs(expr * t) const {
if (m_max_occs == UINT_MAX)
return true;
unsigned num = 0;
m_num_occs.find(t, num);
TRACE("solve_eqs_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_produce_proofs)
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_produce_proofs)
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_produce_proofs)
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_produce_proofs) {
// [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("solve_eqs_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_produce_proofs) {
// [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;
}
/**
\brief Start collecting candidates
*/
void collect(goal const & g) {
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 = g.size();
for (unsigned idx = 0; idx < size; idx++) {
checkpoint();
expr * f = g.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_produce_proofs) {
if (pr == 0)
pr = g.pr(idx);
else
pr = m().mk_modus_ponens(g.pr(idx), pr);
}
m_subst->insert(var, def, pr, g.dep(idx));
}
m_num_steps++;
}
TRACE("solve_eqs",
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("solve_eqs_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("solve_eqs_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;
expr_dependency * dep;
m_subst->find(to_app(t), def, pr, dep);
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;
expr_dependency * dep;
m_subst->find(to_app(t), def, pr, dep);
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("solve_eqs",
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.get());
expr_ref new_def(m());
proof_ref new_pr(m());
expr_dependency_ref new_dep(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;
expr_dependency * dep = 0;
m_subst->find(v, def, pr, dep);
SASSERT(def != 0);
m_r->operator()(def, new_def, new_pr, new_dep);
m_num_steps += m_r->get_num_steps() + 1;
if (m_produce_proofs)
new_pr = m().mk_transitivity(pr, new_pr);
if (m_produce_unsat_cores)
new_dep = m().mk_join(dep, new_dep);
m_norm_subst->insert(v, new_def, new_pr, new_dep);
// 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("solve_eqs",
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;
expr_dependency * dep = 0;
m_norm_subst->find(v, def, pr, dep);
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;
expr_dependency * dep = 0;
m_norm_subst->find(v, def, pr, dep);
SASSERT(def != 0);
CASSERT("solve_eqs_bug", !occurs(v, def));
}
});
#endif
}
void substitute(goal & g) {
// force the cache of m_r to be reset.
m_r->set_substitution(m_norm_subst.get());
expr_ref new_f(m());
proof_ref new_pr(m());
expr_dependency_ref new_dep(m());
unsigned size = g.size();
for (unsigned idx = 0; idx < size; idx++) {
checkpoint();
expr * f = g.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));
g.update(idx, m().mk_true(), m().mk_true_proof(), 0);
m_num_steps ++;
continue;
}
m_r->operator()(f, new_f, new_pr, new_dep);
TRACE("solve_eqs_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_produce_proofs)
new_pr = m().mk_modus_ponens(g.pr(idx), new_pr);
if (m_produce_unsat_cores)
new_dep = m().mk_join(g.dep(idx), new_dep);
g.update(idx, new_f, new_pr, new_dep);
if (g.inconsistent())
return;
}
g.elim_true();
TRACE("solve_eqs",
tout << "after applying substitution\n";
g.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 < g.size(); j++) {
CASSERT("solve_eqs_bug", !occurs(v, g.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;
expr_dependency * dep;
m_norm_subst->find(v, def, pr, dep);
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(goal const & g) {
if (m_max_occs == UINT_MAX)
return; // no need to compute num occs
m_num_occs.reset();
expr_fast_mark1 visited;
unsigned sz = g.size();
for (unsigned i = 0; i < sz; i++)
collect_num_occs(g.form(i), visited);
}
unsigned get_num_steps() const {
return m_num_steps;
}
unsigned get_num_eliminated_vars() const {
return m_num_eliminated_vars;
}
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());
mc = 0; pc = 0; core = 0;
tactic_report report("solve_eqs", *g);
m_produce_models = g->models_enabled();
m_produce_proofs = g->proofs_enabled();
m_produce_unsat_cores = g->unsat_core_enabled();
if (!g->inconsistent()) {
m_subst = alloc(expr_substitution, m(), m_produce_unsat_cores, m_produce_proofs);
m_norm_subst = alloc(expr_substitution, m(), m_produce_unsat_cores, m_produce_proofs);
while (true) {
collect_num_occs(*g);
collect(*g);
if (m_subst->empty())
break;
sort_vars();
if (m_ordered_vars.empty())
break;
normalize();
substitute(*(g.get()));
if (g->inconsistent()) {
mc = 0;
break;
}
save_elim_vars(mc);
TRACE("solve_eqs_round", g->display(tout); if (mc) mc->display(tout););
}
}
g->inc_depth();
result.push_back(g.get());
TRACE("solve_eqs", g->display(tout););
SASSERT(g->is_well_sorted());
}
};
imp * m_imp;
params_ref m_params;
public:
solve_eqs_tactic(ast_manager & m, params_ref const & p, expr_replacer * r, bool owner):
m_params(p) {
m_imp = alloc(imp, m, p, r, owner);
}
virtual tactic * translate(ast_manager & m) {
return alloc(solve_eqs_tactic, m, m_params, mk_expr_simp_replacer(m, m_params), true);
}
virtual ~solve_eqs_tactic() {
dealloc(m_imp);
}
virtual void updt_params(params_ref const & p) {
m_params = p;
m_imp->updt_params(p);
}
virtual void collect_param_descrs(param_descrs & r) {
r.insert(":solve-eqs-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.");
}
virtual void operator()(goal_ref const & in,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
(*m_imp)(in, result, mc, pc, core);
report_tactic_progress(":num-elim-vars", m_imp->get_num_eliminated_vars());
}
virtual void 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;
if (r)
r->set_substitution(0);
bool owner = m_imp->m_r_owner;
m_imp->m_r_owner = false; // stole replacer
#pragma omp critical (tactic_cancel)
{
m_imp = 0;
}
dealloc(d);
d = alloc(imp, m, m_params, r, owner);
#pragma omp critical (tactic_cancel)
{
m_imp = d;
}
m_imp->m_num_eliminated_vars = num_elim_vars;
}
virtual void collect_statistics(statistics & st) const {
st.update("eliminated vars", m_imp->get_num_eliminated_vars());
}
virtual void reset_statistics() {
m_imp->m_num_eliminated_vars = 0;
}
virtual void set_cancel(bool f) {
if (m_imp)
m_imp->set_cancel(f);
}
};
tactic * mk_solve_eqs_tactic(ast_manager & m, params_ref const & p, expr_replacer * r) {
if (r == 0)
return clean(alloc(solve_eqs_tactic, m, p, mk_expr_simp_replacer(m, p), true));
else
return clean(alloc(solve_eqs_tactic, m, p, r, false));
}

View file

@ -0,0 +1,30 @@
/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
solve_eqs_tactic.h
Abstract:
Tactic for solving equations and performing gaussian elimination.
Author:
Leonardo de Moura (leonardo) 2011-12-29.
Revision History:
--*/
#ifndef _SOLVE_EQS_TACTIC_H_
#define _SOLVE_EQS_TACTIC_H_
#include"params.h"
class ast_manager;
class tactic;
class expr_replacer;
tactic * mk_solve_eqs_tactic(ast_manager & m, params_ref const & p = params_ref(), expr_replacer * r = 0);
#endif

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