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:
parent
3003ee5cb6
commit
dcf778a287
120 changed files with 10 additions and 4 deletions
1812
src/aig/aig.cpp
Normal file
1812
src/aig/aig.cpp
Normal file
File diff suppressed because it is too large
Load diff
85
src/aig/aig.h
Normal file
85
src/aig/aig.h
Normal file
|
@ -0,0 +1,85 @@
|
|||
/*++
|
||||
Copyright (c) 2011 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
aig.h
|
||||
|
||||
Abstract:
|
||||
|
||||
And-inverted graphs
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo (leonardo) 2011-05-13
|
||||
|
||||
Notes:
|
||||
|
||||
--*/
|
||||
#ifndef _AIG_H_
|
||||
#define _AIG_H_
|
||||
|
||||
#include"ast.h"
|
||||
#include"tactic_exception.h"
|
||||
|
||||
class assertion_set;
|
||||
class goal;
|
||||
class aig_lit;
|
||||
class aig_manager;
|
||||
|
||||
class aig_exception : public tactic_exception {
|
||||
public:
|
||||
aig_exception(char const * msg):tactic_exception(msg) {}
|
||||
};
|
||||
|
||||
class aig_ref {
|
||||
friend class aig_lit;
|
||||
friend class aig_manager;
|
||||
aig_manager * m_manager;
|
||||
void * m_ref;
|
||||
aig_ref(aig_manager & m, aig_lit const & l);
|
||||
public:
|
||||
aig_ref();
|
||||
~aig_ref();
|
||||
aig_ref & operator=(aig_ref const & r);
|
||||
bool operator==(aig_ref const & r) const { return m_ref == r.m_ref; }
|
||||
bool operator!=(aig_ref const & r) const { return m_ref != r.m_ref; }
|
||||
};
|
||||
|
||||
class aig_manager {
|
||||
struct imp;
|
||||
imp * m_imp;
|
||||
friend class aig_ref;
|
||||
public:
|
||||
// If default_gate_encoding == true, then
|
||||
// ite(a, b, c) is encoded as (NOT a OR b) AND (a OR c)
|
||||
// iff(a, b) is encoded as (NOT a OR b) AND (a OR NOT b)
|
||||
//
|
||||
// If default_gate_encoding == false, then
|
||||
// ite(a, b, c) is encoded as (a AND b) OR (NOT a AND c)
|
||||
// iff(a, b) is encoded as (a AND b) OR (NOT a AND NOT b)
|
||||
aig_manager(ast_manager & m, unsigned long long max_memory = UINT64_MAX, bool default_gate_encoding = true);
|
||||
~aig_manager();
|
||||
void set_max_memory(unsigned long long max);
|
||||
aig_ref mk_aig(expr * n);
|
||||
aig_ref mk_aig(assertion_set const & s); // TODO delete
|
||||
aig_ref mk_aig(goal const & g);
|
||||
aig_ref mk_not(aig_ref const & r);
|
||||
aig_ref mk_and(aig_ref const & r1, aig_ref const & r2);
|
||||
aig_ref mk_or(aig_ref const & r1, aig_ref const & r2);
|
||||
aig_ref mk_iff(aig_ref const & r1, aig_ref const & r2);
|
||||
aig_ref mk_ite(aig_ref const & r1, aig_ref const & r2, aig_ref const & r3);
|
||||
void max_sharing(aig_ref & r);
|
||||
void to_formula(aig_ref const & r, assertion_set & s); // TODO delete
|
||||
void to_formula(aig_ref const & r, expr_ref & result);
|
||||
void to_formula(aig_ref const & r, goal & result);
|
||||
void to_cnf(aig_ref const & r, goal & result);
|
||||
void display(std::ostream & out, aig_ref const & r) const;
|
||||
void display_smt2(std::ostream & out, aig_ref const & r) const;
|
||||
unsigned get_num_aigs() const;
|
||||
void cancel() { set_cancel(true); }
|
||||
void reset_cancel() { set_cancel(false); }
|
||||
void set_cancel(bool f);
|
||||
};
|
||||
|
||||
#endif
|
126
src/aig/aig_tactic.cpp
Normal file
126
src/aig/aig_tactic.cpp
Normal file
|
@ -0,0 +1,126 @@
|
|||
/*++
|
||||
Copyright (c) 2011 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
aig_tactic.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Tactic for minimizing circuits using AIGs.
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo (leonardo) 2011-10-24
|
||||
|
||||
Notes:
|
||||
|
||||
--*/
|
||||
#include"tactical.h"
|
||||
#include"aig.h"
|
||||
|
||||
class aig_manager;
|
||||
|
||||
class aig_tactic : public tactic {
|
||||
unsigned long long m_max_memory;
|
||||
bool m_aig_gate_encoding;
|
||||
bool m_aig_per_assertion;
|
||||
aig_manager * m_aig_manager;
|
||||
|
||||
struct mk_aig_manager {
|
||||
aig_tactic & m_owner;
|
||||
|
||||
mk_aig_manager(aig_tactic & o, ast_manager & m):m_owner(o) {
|
||||
aig_manager * mng = alloc(aig_manager, m, o.m_max_memory, o.m_aig_gate_encoding);
|
||||
#pragma omp critical (aig_tactic)
|
||||
{
|
||||
m_owner.m_aig_manager = mng;
|
||||
}
|
||||
}
|
||||
|
||||
~mk_aig_manager() {
|
||||
aig_manager * mng = m_owner.m_aig_manager;
|
||||
#pragma omp critical (aig_tactic)
|
||||
{
|
||||
m_owner.m_aig_manager = 0;
|
||||
}
|
||||
dealloc(mng);
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
aig_tactic(params_ref const & p = params_ref()):m_aig_manager(0) {
|
||||
updt_params(p);
|
||||
}
|
||||
|
||||
virtual tactic * translate(ast_manager & m) {
|
||||
aig_tactic * t = alloc(aig_tactic);
|
||||
t->m_max_memory = m_max_memory;
|
||||
t->m_aig_gate_encoding = m_aig_gate_encoding;
|
||||
t->m_aig_per_assertion = m_aig_per_assertion;
|
||||
return t;
|
||||
}
|
||||
|
||||
virtual void updt_params(params_ref const & p) {
|
||||
m_max_memory = megabytes_to_bytes(p.get_uint(":max-memory", UINT_MAX));
|
||||
m_aig_gate_encoding = p.get_bool(":aig-default-gate-encoding", true);
|
||||
m_aig_per_assertion = p.get_bool(":aig-per-assertion", true);
|
||||
}
|
||||
|
||||
virtual void collect_param_descrs(param_descrs & r) {
|
||||
insert_max_memory(r);
|
||||
r.insert(":aig-per-assertion", CPK_BOOL, "(default: true) process one assertion at a time.");
|
||||
}
|
||||
|
||||
void operator()(goal_ref const & g) {
|
||||
SASSERT(g->is_well_sorted());
|
||||
tactic_report report("aig", *g);
|
||||
|
||||
mk_aig_manager mk(*this, g->m());
|
||||
if (m_aig_per_assertion) {
|
||||
unsigned size = g->size();
|
||||
for (unsigned i = 0; i < size; i++) {
|
||||
aig_ref r = m_aig_manager->mk_aig(g->form(i));
|
||||
m_aig_manager->max_sharing(r);
|
||||
expr_ref new_f(g->m());
|
||||
m_aig_manager->to_formula(r, new_f);
|
||||
g->update(i, new_f, 0, g->dep(i));
|
||||
}
|
||||
}
|
||||
else {
|
||||
fail_if_unsat_core_generation("aig", g);
|
||||
aig_ref r = m_aig_manager->mk_aig(*(g.get()));
|
||||
g->reset(); // save memory
|
||||
m_aig_manager->max_sharing(r);
|
||||
m_aig_manager->to_formula(r, *(g.get()));
|
||||
}
|
||||
SASSERT(g->is_well_sorted());
|
||||
}
|
||||
|
||||
virtual void operator()(goal_ref const & g,
|
||||
goal_ref_buffer & result,
|
||||
model_converter_ref & mc,
|
||||
proof_converter_ref & pc,
|
||||
expr_dependency_ref & core) {
|
||||
fail_if_proof_generation("aig", g);
|
||||
mc = 0; pc = 0; core = 0;
|
||||
operator()(g);
|
||||
g->inc_depth();
|
||||
result.push_back(g.get());
|
||||
}
|
||||
|
||||
virtual void cleanup() {}
|
||||
|
||||
protected:
|
||||
virtual void set_cancel(bool f) {
|
||||
#pragma omp critical (aig_tactic)
|
||||
{
|
||||
if (m_aig_manager)
|
||||
m_aig_manager->set_cancel(f);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
tactic * mk_aig_tactic(params_ref const & p) {
|
||||
return clean(alloc(aig_tactic, p));
|
||||
}
|
27
src/aig/aig_tactic.h
Normal file
27
src/aig/aig_tactic.h
Normal file
|
@ -0,0 +1,27 @@
|
|||
/*++
|
||||
Copyright (c) 2011 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
aig_tactic.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Tactic for minimizing circuits using AIGs.
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo (leonardo) 2011-10-24
|
||||
|
||||
Notes:
|
||||
|
||||
--*/
|
||||
#ifndef _AIG_TACTIC_H_
|
||||
#define _AIG_TACTIC_H_
|
||||
|
||||
#include"params.h"
|
||||
class tactic;
|
||||
|
||||
tactic * mk_aig_tactic(params_ref const & p = params_ref());
|
||||
|
||||
#endif
|
219
src/api/api_arith.cpp
Normal file
219
src/api/api_arith.cpp
Normal file
|
@ -0,0 +1,219 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
api_arith.cpp
|
||||
|
||||
Abstract:
|
||||
API for arith theory
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2012-02-29.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include<iostream>
|
||||
#include"z3.h"
|
||||
#include"api_log_macros.h"
|
||||
#include"api_context.h"
|
||||
#include"api_util.h"
|
||||
#include"arith_decl_plugin.h"
|
||||
#include"algebraic_numbers.h"
|
||||
|
||||
#define MK_ARITH_OP(NAME, OP) MK_NARY(NAME, mk_c(c)->get_arith_fid(), OP, SKIP)
|
||||
#define MK_BINARY_ARITH_OP(NAME, OP) MK_BINARY(NAME, mk_c(c)->get_arith_fid(), OP, SKIP)
|
||||
#define MK_ARITH_PRED(NAME, OP) MK_BINARY(NAME, mk_c(c)->get_arith_fid(), OP, SKIP)
|
||||
|
||||
extern "C" {
|
||||
|
||||
Z3_sort Z3_API Z3_mk_int_sort(Z3_context c) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_int_sort(c);
|
||||
RESET_ERROR_CODE();
|
||||
Z3_sort r = of_sort(mk_c(c)->m().mk_sort(mk_c(c)->get_arith_fid(), INT_SORT));
|
||||
RETURN_Z3(r);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_sort Z3_API Z3_mk_real_sort(Z3_context c) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_real_sort(c);
|
||||
RESET_ERROR_CODE();
|
||||
Z3_sort r = of_sort(mk_c(c)->m().mk_sort(mk_c(c)->get_arith_fid(), REAL_SORT));
|
||||
RETURN_Z3(r);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_mk_real(__in Z3_context c, int num, int den) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_real(c, num, den);
|
||||
RESET_ERROR_CODE();
|
||||
if (den == 0) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
sort* s = mk_c(c)->m().mk_sort(mk_c(c)->get_arith_fid(), REAL_SORT);
|
||||
ast* a = mk_c(c)->mk_numeral_core(rational(num, den), s);
|
||||
RETURN_Z3(of_ast(a));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
MK_ARITH_OP(Z3_mk_add, OP_ADD);
|
||||
MK_ARITH_OP(Z3_mk_mul, OP_MUL);
|
||||
MK_BINARY_ARITH_OP(Z3_mk_power, OP_POWER);
|
||||
MK_BINARY_ARITH_OP(Z3_mk_mod, OP_MOD);
|
||||
MK_BINARY_ARITH_OP(Z3_mk_rem, OP_REM);
|
||||
|
||||
Z3_ast Z3_API Z3_mk_div(Z3_context c, Z3_ast n1, Z3_ast n2) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_div(c, n1, n2);
|
||||
RESET_ERROR_CODE();
|
||||
decl_kind k = OP_IDIV;
|
||||
sort* ty = mk_c(c)->m().get_sort(to_expr(n1));
|
||||
sort* real_ty = mk_c(c)->m().mk_sort(mk_c(c)->get_arith_fid(), REAL_SORT);
|
||||
if (ty == real_ty) {
|
||||
k = OP_DIV;
|
||||
}
|
||||
expr * args[2] = { to_expr(n1), to_expr(n2) };
|
||||
ast* a = mk_c(c)->m().mk_app(mk_c(c)->get_arith_fid(), k, 0, 0, 2, args);
|
||||
mk_c(c)->save_ast_trail(a);
|
||||
check_sorts(c, a);
|
||||
RETURN_Z3(of_ast(a));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
MK_ARITH_PRED(Z3_mk_lt, OP_LT);
|
||||
MK_ARITH_PRED(Z3_mk_gt, OP_GT);
|
||||
MK_ARITH_PRED(Z3_mk_le, OP_LE);
|
||||
MK_ARITH_PRED(Z3_mk_ge, OP_GE);
|
||||
MK_UNARY(Z3_mk_int2real, mk_c(c)->get_arith_fid(), OP_TO_REAL, SKIP);
|
||||
MK_UNARY(Z3_mk_real2int, mk_c(c)->get_arith_fid(), OP_TO_INT, SKIP);
|
||||
MK_UNARY(Z3_mk_is_int, mk_c(c)->get_arith_fid(), OP_IS_INT, SKIP);
|
||||
|
||||
Z3_ast Z3_API Z3_mk_sub(Z3_context c, unsigned num_args, Z3_ast const args[]) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_sub(c, num_args, args);
|
||||
RESET_ERROR_CODE();
|
||||
if (num_args == 0) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
if (mk_c(c)->fparams().m_pre_simplify_expr) {
|
||||
// Do not use logging here... the function is implemented using API primitives
|
||||
Z3_ast m1 = Z3_mk_int(c, -1, Z3_get_sort(c, args[0]));
|
||||
Z3_ast args1[2] = { args[0], 0 };
|
||||
for (unsigned i = 1; i < num_args; ++i) {
|
||||
Z3_ast args2[3] = { m1, args[i] };
|
||||
args1[1] = Z3_mk_mul(c, 2, args2);
|
||||
args1[0] = Z3_mk_add(c, 2, args1);
|
||||
}
|
||||
RETURN_Z3(args1[0]);
|
||||
}
|
||||
else {
|
||||
expr* r = to_expr(args[0]);
|
||||
for (unsigned i = 1; i < num_args; ++i) {
|
||||
expr* args1[2] = { r, to_expr(args[i]) };
|
||||
r = mk_c(c)->m().mk_app(mk_c(c)->get_arith_fid(), OP_SUB, 0, 0, 2, args1);
|
||||
check_sorts(c, r);
|
||||
}
|
||||
mk_c(c)->save_ast_trail(r);
|
||||
RETURN_Z3(of_expr(r));
|
||||
}
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_mk_unary_minus(Z3_context c, Z3_ast n) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_unary_minus(c, n);
|
||||
RESET_ERROR_CODE();
|
||||
if (mk_c(c)->fparams().m_pre_simplify_expr) {
|
||||
Z3_ast m1 = Z3_mk_int(c, -1, Z3_get_sort(c, n));
|
||||
Z3_ast args[2] = { m1, n };
|
||||
Z3_ast r = Z3_mk_mul(c, 2, args);
|
||||
RETURN_Z3(r);
|
||||
}
|
||||
MK_UNARY_BODY(Z3_mk_unary_minus, mk_c(c)->get_arith_fid(), OP_UMINUS, SKIP);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_bool Z3_API Z3_is_algebraic_number(Z3_context c, Z3_ast a) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_is_algebraic_number(c, a);
|
||||
RESET_ERROR_CODE();
|
||||
expr * e = to_expr(a);
|
||||
return mk_c(c)->autil().is_irrational_algebraic_numeral(e);
|
||||
Z3_CATCH_RETURN(Z3_FALSE);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_get_algebraic_number_lower(Z3_context c, Z3_ast a, unsigned precision) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_algebraic_number_lower(c, a, precision);
|
||||
RESET_ERROR_CODE();
|
||||
if (!Z3_is_algebraic_number(c, a)) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
expr * e = to_expr(a);
|
||||
algebraic_numbers::anum const & val = mk_c(c)->autil().to_irrational_algebraic_numeral(e);
|
||||
rational l;
|
||||
mk_c(c)->autil().am().get_lower(val, l, precision);
|
||||
expr * r = mk_c(c)->autil().mk_numeral(l, false);
|
||||
mk_c(c)->save_ast_trail(r);
|
||||
RETURN_Z3(of_expr(r));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_get_algebraic_number_upper(Z3_context c, Z3_ast a, unsigned precision) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_algebraic_number_upper(c, a, precision);
|
||||
RESET_ERROR_CODE();
|
||||
if (!Z3_is_algebraic_number(c, a)) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
expr * e = to_expr(a);
|
||||
algebraic_numbers::anum const & val = mk_c(c)->autil().to_irrational_algebraic_numeral(e);
|
||||
rational l;
|
||||
mk_c(c)->autil().am().get_upper(val, l, precision);
|
||||
expr * r = mk_c(c)->autil().mk_numeral(l, false);
|
||||
mk_c(c)->save_ast_trail(r);
|
||||
RETURN_Z3(of_expr(r));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_get_numerator(Z3_context c, Z3_ast a) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_numerator(c, a);
|
||||
RESET_ERROR_CODE();
|
||||
rational val;
|
||||
ast * _a = to_ast(a);
|
||||
if (!is_expr(_a) || !mk_c(c)->autil().is_numeral(to_expr(_a), val)) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
expr * r = mk_c(c)->autil().mk_numeral(numerator(val), true);
|
||||
mk_c(c)->save_ast_trail(r);
|
||||
RETURN_Z3(of_expr(r));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_get_denominator(Z3_context c, Z3_ast a) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_denominator(c, a);
|
||||
RESET_ERROR_CODE();
|
||||
rational val;
|
||||
ast * _a = to_ast(a);
|
||||
if (!is_expr(_a) || !mk_c(c)->autil().is_numeral(to_expr(_a), val)) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
expr * r = mk_c(c)->autil().mk_numeral(denominator(val), true);
|
||||
mk_c(c)->save_ast_trail(r);
|
||||
RETURN_Z3(of_expr(r));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
};
|
233
src/api/api_array.cpp
Normal file
233
src/api/api_array.cpp
Normal file
|
@ -0,0 +1,233 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
api_array.cpp
|
||||
|
||||
Abstract:
|
||||
API for array theory
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2012-02-29.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include<iostream>
|
||||
#include"z3.h"
|
||||
#include"api_log_macros.h"
|
||||
#include"api_context.h"
|
||||
#include"api_util.h"
|
||||
#include"array_decl_plugin.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
Z3_sort Z3_API Z3_mk_array_sort(Z3_context c, Z3_sort domain, Z3_sort range) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_array_sort(c, domain, range);
|
||||
RESET_ERROR_CODE();
|
||||
parameter params[2] = { parameter(to_sort(domain)), parameter(to_sort(range)) };
|
||||
sort * ty = mk_c(c)->m().mk_sort(mk_c(c)->get_array_fid(), ARRAY_SORT, 2, params);
|
||||
mk_c(c)->save_ast_trail(ty);
|
||||
RETURN_Z3(of_sort(ty));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_mk_select(Z3_context c, Z3_ast a, Z3_ast i) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_select(c, a, i);
|
||||
RESET_ERROR_CODE();
|
||||
ast_manager & m = mk_c(c)->m();
|
||||
expr * _a = to_expr(a);
|
||||
expr * _i = to_expr(i);
|
||||
sort * a_ty = m.get_sort(_a);
|
||||
sort * i_ty = m.get_sort(_i);
|
||||
if (a_ty->get_family_id() != mk_c(c)->get_array_fid()) {
|
||||
SET_ERROR_CODE(Z3_SORT_ERROR);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
sort * domain[2] = {a_ty, i_ty};
|
||||
func_decl * d = m.mk_func_decl(mk_c(c)->get_array_fid(), OP_SELECT, 2, a_ty->get_parameters(), 2, domain);
|
||||
expr * args[2] = {_a, _i};
|
||||
app * r = m.mk_app(d, 2, args);
|
||||
mk_c(c)->save_ast_trail(r);
|
||||
check_sorts(c, r);
|
||||
RETURN_Z3(of_ast(r));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_mk_store(Z3_context c, Z3_ast a, Z3_ast i, Z3_ast v) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_store(c, a, i, v);
|
||||
RESET_ERROR_CODE();
|
||||
ast_manager & m = mk_c(c)->m();
|
||||
expr * _a = to_expr(a);
|
||||
expr * _i = to_expr(i);
|
||||
expr * _v = to_expr(v);
|
||||
sort * a_ty = m.get_sort(_a);
|
||||
sort * i_ty = m.get_sort(_i);
|
||||
sort * v_ty = m.get_sort(_v);
|
||||
if (a_ty->get_family_id() != mk_c(c)->get_array_fid()) {
|
||||
SET_ERROR_CODE(Z3_SORT_ERROR);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
sort * domain[3] = {a_ty, i_ty, v_ty};
|
||||
func_decl * d = m.mk_func_decl(mk_c(c)->get_array_fid(), OP_STORE, 2, a_ty->get_parameters(), 3, domain);
|
||||
expr * args[3] = {_a, _i, _v};
|
||||
app * r = m.mk_app(d, 3, args);
|
||||
mk_c(c)->save_ast_trail(r);
|
||||
check_sorts(c, r);
|
||||
RETURN_Z3(of_ast(r));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_mk_map(__in Z3_context c, __in Z3_func_decl f, unsigned n, __in Z3_ast const* args) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_map(c, f, n, args);
|
||||
RESET_ERROR_CODE();
|
||||
if (n == 0) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
ast_manager & m = mk_c(c)->m();
|
||||
func_decl* _f = to_func_decl(f);
|
||||
expr* const* _args = to_exprs(args);
|
||||
|
||||
ptr_vector<sort> domain;
|
||||
for (unsigned i = 0; i < n; ++i) {
|
||||
domain.push_back(m.get_sort(_args[i]));
|
||||
}
|
||||
parameter param(_f);
|
||||
func_decl * d = m.mk_func_decl(mk_c(c)->get_array_fid(), OP_ARRAY_MAP, 1, ¶m, n, domain.c_ptr());
|
||||
app* r = m.mk_app(d, n, _args);
|
||||
mk_c(c)->save_ast_trail(r);
|
||||
check_sorts(c, r);
|
||||
RETURN_Z3(of_ast(r));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_mk_const_array(__in Z3_context c, __in Z3_sort domain, __in Z3_ast v) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_const_array(c, domain, v);
|
||||
RESET_ERROR_CODE();
|
||||
ast_manager & m = mk_c(c)->m();
|
||||
expr * _v = to_expr(v);
|
||||
sort * _range = m.get_sort(_v);
|
||||
sort * _domain = to_sort(domain);
|
||||
parameter params[2] = { parameter(_domain), parameter(_range) };
|
||||
sort * a_ty = mk_c(c)->m().mk_sort(mk_c(c)->get_array_fid(), ARRAY_SORT, 2, params);
|
||||
parameter param(a_ty);
|
||||
func_decl* cd = m.mk_func_decl(mk_c(c)->get_array_fid(), OP_CONST_ARRAY, 1, ¶m, 1, &_range);
|
||||
app * r = m.mk_app(cd, 1, &_v);
|
||||
mk_c(c)->save_ast_trail(r);
|
||||
check_sorts(c, r);
|
||||
RETURN_Z3(of_ast(r));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_mk_array_default(__in Z3_context c, __in Z3_ast array) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_array_default(c, array);
|
||||
RESET_ERROR_CODE();
|
||||
ast_manager & m = mk_c(c)->m();
|
||||
expr * _a = to_expr(array);
|
||||
|
||||
func_decl * f = m.mk_func_decl(mk_c(c)->get_array_fid(), OP_ARRAY_DEFAULT, 0, 0, 1, &_a);
|
||||
app * r = m.mk_app(f, 1, &_a);
|
||||
mk_c(c)->save_ast_trail(r);
|
||||
check_sorts(c, r);
|
||||
RETURN_Z3(of_ast(r));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast mk_app_array_core(__in Z3_context c, __in Z3_sort domain, __in Z3_ast v) {
|
||||
RESET_ERROR_CODE();
|
||||
ast_manager & m = mk_c(c)->m();
|
||||
expr * _v = to_expr(v);
|
||||
sort * _range = m.get_sort(_v);
|
||||
sort * _domain = to_sort(domain);
|
||||
parameter params[2] = { parameter(_domain), parameter(_range) };
|
||||
sort * a_ty = mk_c(c)->m().mk_sort(mk_c(c)->get_array_fid(), ARRAY_SORT, 2, params);
|
||||
parameter param(a_ty);
|
||||
func_decl * cd = m.mk_func_decl(mk_c(c)->get_array_fid(), OP_CONST_ARRAY, 1, ¶m, 1, &_range);
|
||||
app * r = m.mk_app(cd, 1, &_v);
|
||||
mk_c(c)->save_ast_trail(r);
|
||||
check_sorts(c, r);
|
||||
return of_ast(r);
|
||||
}
|
||||
|
||||
Z3_sort Z3_API Z3_mk_set_sort(__in Z3_context c, __in Z3_sort ty) {
|
||||
Z3_TRY;
|
||||
return Z3_mk_array_sort(c, ty, Z3_mk_bool_sort(c));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_mk_empty_set(__in Z3_context c, __in Z3_sort domain) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_empty_set(c, domain);
|
||||
RESET_ERROR_CODE();
|
||||
Z3_ast r = mk_app_array_core(c, domain, Z3_mk_false(c));
|
||||
RETURN_Z3(r);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_mk_full_set(__in Z3_context c, __in Z3_sort domain) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_full_set(c, domain);
|
||||
RESET_ERROR_CODE();
|
||||
Z3_ast r = mk_app_array_core(c, domain, Z3_mk_true(c));
|
||||
RETURN_Z3(r);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
MK_NARY(Z3_mk_set_union, mk_c(c)->get_array_fid(), OP_SET_UNION, SKIP);
|
||||
MK_NARY(Z3_mk_set_intersect, mk_c(c)->get_array_fid(), OP_SET_INTERSECT, SKIP);
|
||||
MK_BINARY(Z3_mk_set_difference, mk_c(c)->get_array_fid(), OP_SET_DIFFERENCE, SKIP);
|
||||
MK_UNARY(Z3_mk_set_complement, mk_c(c)->get_array_fid(), OP_SET_COMPLEMENT, SKIP);
|
||||
MK_BINARY(Z3_mk_set_subset, mk_c(c)->get_array_fid(), OP_SET_SUBSET, SKIP);
|
||||
|
||||
Z3_ast Z3_mk_set_member(__in Z3_context c, __in Z3_ast elem, __in Z3_ast set) {
|
||||
return Z3_mk_select(c, set, elem);
|
||||
}
|
||||
|
||||
Z3_ast Z3_mk_set_add(__in Z3_context c, __in Z3_ast set, __in Z3_ast elem) {
|
||||
return Z3_mk_store(c, set, elem, Z3_mk_true(c));
|
||||
}
|
||||
|
||||
Z3_ast Z3_mk_set_del(__in Z3_context c, __in Z3_ast set, __in Z3_ast elem) {
|
||||
return Z3_mk_store(c, set, elem, Z3_mk_false(c));
|
||||
}
|
||||
|
||||
Z3_sort Z3_API Z3_get_array_sort_domain(Z3_context c, Z3_sort t) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_array_sort_domain(c, t);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_VALID_AST(t, 0);
|
||||
if (to_sort(t)->get_family_id() == mk_c(c)->get_array_fid() &&
|
||||
to_sort(t)->get_decl_kind() == ARRAY_SORT) {
|
||||
Z3_sort r = reinterpret_cast<Z3_sort>(to_sort(t)->get_parameter(0).get_ast());
|
||||
RETURN_Z3(r);
|
||||
}
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_sort Z3_API Z3_get_array_sort_range(Z3_context c, Z3_sort t) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_array_sort_range(c, t);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_VALID_AST(t, 0);
|
||||
if (to_sort(t)->get_family_id() == mk_c(c)->get_array_fid() &&
|
||||
to_sort(t)->get_decl_kind() == ARRAY_SORT) {
|
||||
Z3_sort r = reinterpret_cast<Z3_sort>(to_sort(t)->get_parameter(1).get_ast());
|
||||
RETURN_Z3(r);
|
||||
}
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
};
|
1156
src/api/api_ast.cpp
Normal file
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
169
src/api/api_ast_map.cpp
Normal file
|
@ -0,0 +1,169 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
api_ast_map.cpp
|
||||
|
||||
Abstract:
|
||||
API for creating AST maps
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2012-03-09.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include<iostream>
|
||||
#include"z3.h"
|
||||
#include"api_log_macros.h"
|
||||
#include"api_context.h"
|
||||
#include"api_ast_map.h"
|
||||
#include"api_ast_vector.h"
|
||||
#include"ast_smt2_pp.h"
|
||||
#include"dec_ref_util.h"
|
||||
|
||||
Z3_ast_map_ref::~Z3_ast_map_ref() {
|
||||
dec_ref_key_values(m, m_map);
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
Z3_ast_map Z3_API Z3_mk_ast_map(Z3_context c) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_ast_map(c);
|
||||
RESET_ERROR_CODE();
|
||||
Z3_ast_map_ref * m = alloc(Z3_ast_map_ref, mk_c(c)->m());
|
||||
mk_c(c)->save_object(m);
|
||||
Z3_ast_map r = of_ast_map(m);
|
||||
RETURN_Z3(r);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
void Z3_API Z3_ast_map_inc_ref(Z3_context c, Z3_ast_map m) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_ast_map_inc_ref(c, m);
|
||||
RESET_ERROR_CODE();
|
||||
to_ast_map(m)->inc_ref();
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_ast_map_dec_ref(Z3_context c, Z3_ast_map m) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_ast_map_dec_ref(c, m);
|
||||
RESET_ERROR_CODE();
|
||||
to_ast_map(m)->dec_ref();
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
Z3_bool Z3_API Z3_ast_map_contains(Z3_context c, Z3_ast_map m, Z3_ast k) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_ast_map_contains(c, m, k);
|
||||
RESET_ERROR_CODE();
|
||||
return to_ast_map_ref(m).contains(to_ast(k));
|
||||
Z3_CATCH_RETURN(Z3_FALSE);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_ast_map_find(Z3_context c, Z3_ast_map m, Z3_ast k) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_ast_map_find(c, m, k);
|
||||
RESET_ERROR_CODE();
|
||||
obj_map<ast, ast*>::obj_map_entry * entry = to_ast_map_ref(m).find_core(to_ast(k));
|
||||
if (entry == 0) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
else {
|
||||
ast * r = entry->get_data().m_value;
|
||||
RETURN_Z3(of_ast(r));
|
||||
}
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
void Z3_API Z3_ast_map_insert(Z3_context c, Z3_ast_map m, Z3_ast k, Z3_ast v) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_ast_map_insert(c, m, k, v);
|
||||
RESET_ERROR_CODE();
|
||||
ast_manager & mng = to_ast_map(m)->m;
|
||||
obj_map<ast, ast*>::obj_map_entry * entry = to_ast_map_ref(m).insert_if_not_there2(to_ast(k), 0);
|
||||
if (entry->get_data().m_value == 0) {
|
||||
// new entry
|
||||
mng.inc_ref(to_ast(k));
|
||||
mng.inc_ref(to_ast(v));
|
||||
entry->get_data().m_value = to_ast(v);
|
||||
}
|
||||
else {
|
||||
// replacing entry
|
||||
mng.inc_ref(to_ast(v));
|
||||
mng.dec_ref(entry->get_data().m_value);
|
||||
entry->get_data().m_value = to_ast(v);
|
||||
}
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_ast_map_reset(Z3_context c, Z3_ast_map m) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_ast_map_reset(c, m);
|
||||
RESET_ERROR_CODE();
|
||||
dec_ref_key_values(to_ast_map(m)->m, to_ast_map_ref(m));
|
||||
SASSERT(to_ast_map_ref(m).empty());
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_ast_map_erase(Z3_context c, Z3_ast_map m, Z3_ast k) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_ast_map_erase(c, m, k);
|
||||
RESET_ERROR_CODE();
|
||||
ast * v = 0;
|
||||
if (to_ast_map_ref(m).find(to_ast(k), v)) {
|
||||
to_ast_map_ref(m).erase(to_ast(k));
|
||||
ast_manager & mng = to_ast_map(m)->m;
|
||||
mng.dec_ref(to_ast(k));
|
||||
mng.dec_ref(v);
|
||||
}
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
unsigned Z3_API Z3_ast_map_size(Z3_context c, Z3_ast_map m) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_ast_map_size(c, m);
|
||||
RESET_ERROR_CODE();
|
||||
return to_ast_map_ref(m).size();
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast_vector Z3_API Z3_ast_map_keys(Z3_context c, Z3_ast_map m) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_ast_map_keys(c, m);
|
||||
RESET_ERROR_CODE();
|
||||
Z3_ast_vector_ref * v = alloc(Z3_ast_vector_ref, to_ast_map(m)->m);
|
||||
mk_c(c)->save_object(v);
|
||||
obj_map<ast, ast*>::iterator it = to_ast_map_ref(m).begin();
|
||||
obj_map<ast, ast*>::iterator end = to_ast_map_ref(m).end();
|
||||
for (; it != end; ++it) {
|
||||
v->m_ast_vector.push_back(it->m_key);
|
||||
}
|
||||
Z3_ast_vector r = of_ast_vector(v);
|
||||
RETURN_Z3(r);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_string Z3_API Z3_ast_map_to_string(Z3_context c, Z3_ast_map m) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_ast_map_to_string(c, m);
|
||||
RESET_ERROR_CODE();
|
||||
std::ostringstream buffer;
|
||||
ast_manager & mng = to_ast_map(m)->m;
|
||||
buffer << "(ast-map";
|
||||
obj_map<ast, ast*>::iterator it = to_ast_map_ref(m).begin();
|
||||
obj_map<ast, ast*>::iterator end = to_ast_map_ref(m).end();
|
||||
for (; it != end; ++it) {
|
||||
buffer << "\n (" << mk_ismt2_pp(it->m_key, mng, 3) << "\n " << mk_ismt2_pp(it->m_value, mng, 3) << ")";
|
||||
}
|
||||
buffer << ")";
|
||||
return mk_c(c)->mk_external_string(buffer.str());
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
};
|
35
src/api/api_ast_map.h
Normal file
35
src/api/api_ast_map.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
api_ast_map.h
|
||||
|
||||
Abstract:
|
||||
API for creating AST maps
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2012-03-09.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _API_AST_MAP_H_
|
||||
#define _API_AST_MAP_H_
|
||||
|
||||
#include"api_util.h"
|
||||
#include"obj_hashtable.h"
|
||||
|
||||
struct Z3_ast_map_ref : public api::object {
|
||||
ast_manager & m;
|
||||
obj_map<ast, ast*> m_map;
|
||||
Z3_ast_map_ref(ast_manager & _m):m(_m) {}
|
||||
virtual ~Z3_ast_map_ref();
|
||||
};
|
||||
|
||||
inline Z3_ast_map_ref * to_ast_map(Z3_ast_map v) { return reinterpret_cast<Z3_ast_map_ref *>(v); }
|
||||
inline Z3_ast_map of_ast_map(Z3_ast_map_ref * v) { return reinterpret_cast<Z3_ast_map>(v); }
|
||||
inline obj_map<ast, ast*> & to_ast_map_ref(Z3_ast_map v) { return to_ast_map(v)->m_map; }
|
||||
|
||||
#endif
|
140
src/api/api_ast_vector.cpp
Normal file
140
src/api/api_ast_vector.cpp
Normal file
|
@ -0,0 +1,140 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
api_ast_vector.cpp
|
||||
|
||||
Abstract:
|
||||
API for creating AST vectors
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2012-03-09.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include<iostream>
|
||||
#include"z3.h"
|
||||
#include"api_log_macros.h"
|
||||
#include"api_context.h"
|
||||
#include"api_ast_vector.h"
|
||||
#include"ast_translation.h"
|
||||
#include"ast_smt2_pp.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
Z3_ast_vector Z3_API Z3_mk_ast_vector(Z3_context c) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_ast_vector(c);
|
||||
RESET_ERROR_CODE();
|
||||
Z3_ast_vector_ref * v = alloc(Z3_ast_vector_ref, mk_c(c)->m());
|
||||
mk_c(c)->save_object(v);
|
||||
Z3_ast_vector r = of_ast_vector(v);
|
||||
RETURN_Z3(r);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
void Z3_API Z3_ast_vector_inc_ref(Z3_context c, Z3_ast_vector v) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_ast_vector_inc_ref(c, v);
|
||||
RESET_ERROR_CODE();
|
||||
to_ast_vector(v)->inc_ref();
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_ast_vector_dec_ref(Z3_context c, Z3_ast_vector v) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_ast_vector_dec_ref(c, v);
|
||||
RESET_ERROR_CODE();
|
||||
to_ast_vector(v)->dec_ref();
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
unsigned Z3_API Z3_ast_vector_size(Z3_context c, Z3_ast_vector v) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_ast_vector_size(c, v);
|
||||
RESET_ERROR_CODE();
|
||||
return to_ast_vector_ref(v).size();
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_ast_vector_get(Z3_context c, Z3_ast_vector v, unsigned i) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_ast_vector_get(c, v, i);
|
||||
RESET_ERROR_CODE();
|
||||
if (i >= to_ast_vector_ref(v).size()) {
|
||||
SET_ERROR_CODE(Z3_IOB);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
// Remark: Don't need to invoke save_object.
|
||||
ast * r = to_ast_vector_ref(v).get(i);
|
||||
RETURN_Z3(of_ast(r));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
void Z3_API Z3_ast_vector_set(Z3_context c, Z3_ast_vector v, unsigned i, Z3_ast a) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_ast_vector_set(c, v, i, a);
|
||||
RESET_ERROR_CODE();
|
||||
if (i >= to_ast_vector_ref(v).size()) {
|
||||
SET_ERROR_CODE(Z3_IOB);
|
||||
return;
|
||||
}
|
||||
to_ast_vector_ref(v).set(i, to_ast(a));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_ast_vector_resize(Z3_context c, Z3_ast_vector v, unsigned n) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_ast_vector_resize(c, v, n);
|
||||
RESET_ERROR_CODE();
|
||||
to_ast_vector_ref(v).resize(n);
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_ast_vector_push(Z3_context c, Z3_ast_vector v, Z3_ast a) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_ast_vector_push(c, v, a);
|
||||
RESET_ERROR_CODE();
|
||||
to_ast_vector_ref(v).push_back(to_ast(a));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
Z3_ast_vector Z3_API Z3_ast_vector_translate(Z3_context c, Z3_ast_vector v, Z3_context t) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_ast_vector_translate(c, v, t);
|
||||
RESET_ERROR_CODE();
|
||||
if (c == t) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
ast_translation translator(mk_c(c)->m(), mk_c(t)->m());
|
||||
Z3_ast_vector_ref * new_v = alloc(Z3_ast_vector_ref, mk_c(t)->m());
|
||||
mk_c(t)->save_object(new_v);
|
||||
unsigned sz = to_ast_vector_ref(v).size();
|
||||
for (unsigned i = 0; i < sz; i++) {
|
||||
ast * new_ast = translator(to_ast_vector_ref(v).get(i));
|
||||
new_v->m_ast_vector.push_back(new_ast);
|
||||
}
|
||||
RETURN_Z3(of_ast_vector(new_v));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_string Z3_API Z3_ast_vector_to_string(Z3_context c, Z3_ast_vector v) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_ast_vector_to_string(c, v);
|
||||
RESET_ERROR_CODE();
|
||||
std::ostringstream buffer;
|
||||
buffer << "(ast-vector";
|
||||
unsigned sz = to_ast_vector_ref(v).size();
|
||||
for (unsigned i = 0; i < sz; i++) {
|
||||
buffer << "\n " << mk_ismt2_pp(to_ast_vector_ref(v).get(i), mk_c(c)->m(), 2);
|
||||
}
|
||||
buffer << ")";
|
||||
return mk_c(c)->mk_external_string(buffer.str());
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
};
|
33
src/api/api_ast_vector.h
Normal file
33
src/api/api_ast_vector.h
Normal file
|
@ -0,0 +1,33 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
api_ast_vector.h
|
||||
|
||||
Abstract:
|
||||
API for creating AST vectors
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2012-03-09.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _API_AST_VECTOR_H_
|
||||
#define _API_AST_VECTOR_H_
|
||||
|
||||
#include"api_util.h"
|
||||
|
||||
struct Z3_ast_vector_ref : public api::object {
|
||||
ast_ref_vector m_ast_vector;
|
||||
Z3_ast_vector_ref(ast_manager & m):m_ast_vector(m) {}
|
||||
virtual ~Z3_ast_vector_ref() {}
|
||||
};
|
||||
|
||||
inline Z3_ast_vector_ref * to_ast_vector(Z3_ast_vector v) { return reinterpret_cast<Z3_ast_vector_ref *>(v); }
|
||||
inline Z3_ast_vector of_ast_vector(Z3_ast_vector_ref * v) { return reinterpret_cast<Z3_ast_vector>(v); }
|
||||
inline ast_ref_vector & to_ast_vector_ref(Z3_ast_vector v) { return to_ast_vector(v)->m_ast_vector; }
|
||||
|
||||
#endif
|
320
src/api/api_bv.cpp
Normal file
320
src/api/api_bv.cpp
Normal file
|
@ -0,0 +1,320 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
api_bv.cpp
|
||||
|
||||
Abstract:
|
||||
API for bv theory
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2012-02-29.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include<iostream>
|
||||
#include"z3.h"
|
||||
#include"api_log_macros.h"
|
||||
#include"api_context.h"
|
||||
#include"api_util.h"
|
||||
#include"bv_decl_plugin.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
Z3_sort Z3_API Z3_mk_bv_sort(Z3_context c, unsigned sz) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_bv_sort(c, sz);
|
||||
RESET_ERROR_CODE();
|
||||
if (sz == 0) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
}
|
||||
parameter p(sz);
|
||||
Z3_sort r = of_sort(mk_c(c)->m().mk_sort(mk_c(c)->get_bv_fid(), BV_SORT, 1, &p));
|
||||
RETURN_Z3(r);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
#define MK_BV_UNARY(NAME, OP) MK_UNARY(NAME, mk_c(c)->get_bv_fid(), OP, SKIP)
|
||||
#define MK_BV_BINARY(NAME, OP) MK_BINARY(NAME, mk_c(c)->get_bv_fid(), OP, SKIP)
|
||||
|
||||
MK_BV_UNARY(Z3_mk_bvnot, OP_BNOT);
|
||||
MK_BV_UNARY(Z3_mk_bvredand, OP_BREDAND);
|
||||
MK_BV_UNARY(Z3_mk_bvredor, OP_BREDOR);
|
||||
MK_BV_BINARY(Z3_mk_bvand, OP_BAND);
|
||||
MK_BV_BINARY(Z3_mk_bvor, OP_BOR);
|
||||
MK_BV_BINARY(Z3_mk_bvxor, OP_BXOR);
|
||||
MK_BV_BINARY(Z3_mk_bvnand, OP_BNAND);
|
||||
MK_BV_BINARY(Z3_mk_bvnor, OP_BNOR);
|
||||
MK_BV_BINARY(Z3_mk_bvxnor, OP_BXNOR);
|
||||
MK_BV_BINARY(Z3_mk_bvadd, OP_BADD);
|
||||
MK_BV_BINARY(Z3_mk_bvmul, OP_BMUL);
|
||||
MK_BV_BINARY(Z3_mk_bvudiv, OP_BUDIV);
|
||||
MK_BV_BINARY(Z3_mk_bvsdiv, OP_BSDIV);
|
||||
MK_BV_BINARY(Z3_mk_bvurem, OP_BUREM);
|
||||
MK_BV_BINARY(Z3_mk_bvsrem, OP_BSREM);
|
||||
MK_BV_BINARY(Z3_mk_bvsmod, OP_BSMOD);
|
||||
MK_BV_BINARY(Z3_mk_bvule, OP_ULEQ);
|
||||
MK_BV_BINARY(Z3_mk_bvsle, OP_SLEQ);
|
||||
MK_BV_BINARY(Z3_mk_bvuge, OP_UGEQ);
|
||||
MK_BV_BINARY(Z3_mk_bvsge, OP_SGEQ);
|
||||
MK_BV_BINARY(Z3_mk_bvult, OP_ULT);
|
||||
MK_BV_BINARY(Z3_mk_bvslt, OP_SLT);
|
||||
MK_BV_BINARY(Z3_mk_bvugt, OP_UGT);
|
||||
MK_BV_BINARY(Z3_mk_bvsgt, OP_SGT);
|
||||
MK_BV_BINARY(Z3_mk_concat, OP_CONCAT);
|
||||
MK_BV_BINARY(Z3_mk_bvshl, OP_BSHL);
|
||||
MK_BV_BINARY(Z3_mk_bvlshr, OP_BLSHR);
|
||||
MK_BV_BINARY(Z3_mk_bvashr, OP_BASHR);
|
||||
MK_BV_BINARY(Z3_mk_ext_rotate_left, OP_EXT_ROTATE_LEFT);
|
||||
MK_BV_BINARY(Z3_mk_ext_rotate_right, OP_EXT_ROTATE_RIGHT);
|
||||
|
||||
Z3_ast mk_extract_core(Z3_context c, unsigned high, unsigned low, Z3_ast n) {
|
||||
expr * _n = to_expr(n);
|
||||
parameter params[2] = { parameter(high), parameter(low) };
|
||||
expr * a = mk_c(c)->m().mk_app(mk_c(c)->get_bv_fid(), OP_EXTRACT, 2, params, 1, &_n);
|
||||
mk_c(c)->save_ast_trail(a);
|
||||
check_sorts(c, a);
|
||||
return of_ast(a);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_mk_extract(Z3_context c, unsigned high, unsigned low, Z3_ast n) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_extract(c, high, low, n);
|
||||
RESET_ERROR_CODE();
|
||||
Z3_ast r = mk_extract_core(c, high, low, n);
|
||||
RETURN_Z3(r);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
#define MK_BV_PUNARY(NAME, OP) \
|
||||
Z3_ast Z3_API NAME(Z3_context c, unsigned i, Z3_ast n) { \
|
||||
Z3_TRY; \
|
||||
LOG_ ## NAME(c, i, n); \
|
||||
RESET_ERROR_CODE(); \
|
||||
expr * _n = to_expr(n); \
|
||||
parameter p(i); \
|
||||
ast* a = mk_c(c)->m().mk_app(mk_c(c)->get_bv_fid(), OP, 1, &p, 1, &_n); \
|
||||
mk_c(c)->save_ast_trail(a); \
|
||||
check_sorts(c, a); \
|
||||
RETURN_Z3(of_ast(a)); \
|
||||
Z3_CATCH_RETURN(0); \
|
||||
}
|
||||
|
||||
MK_BV_PUNARY(Z3_mk_sign_ext, OP_SIGN_EXT);
|
||||
MK_BV_PUNARY(Z3_mk_zero_ext, OP_ZERO_EXT);
|
||||
MK_BV_PUNARY(Z3_mk_repeat, OP_REPEAT);
|
||||
MK_BV_PUNARY(Z3_mk_rotate_left, OP_ROTATE_LEFT);
|
||||
MK_BV_PUNARY(Z3_mk_rotate_right, OP_ROTATE_RIGHT);
|
||||
MK_BV_PUNARY(Z3_mk_int2bv, OP_INT2BV);
|
||||
|
||||
Z3_ast Z3_API Z3_mk_bv2int(Z3_context c, Z3_ast n, Z3_bool is_signed) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_bv2int(c, n, is_signed);
|
||||
RESET_ERROR_CODE();
|
||||
Z3_sort int_s = Z3_mk_int_sort(c);
|
||||
if (is_signed) {
|
||||
Z3_ast r = Z3_mk_bv2int(c, n, false);
|
||||
Z3_sort s = Z3_get_sort(c, n);
|
||||
unsigned sz = Z3_get_bv_sort_size(c, s);
|
||||
rational max_bound = power(rational(2), sz);
|
||||
Z3_ast bound = Z3_mk_numeral(c, max_bound.to_string().c_str(), int_s);
|
||||
Z3_ast pred = Z3_mk_bvslt(c, n, Z3_mk_int(c, 0, s));
|
||||
// if n <_sigend 0 then r - s^sz else r
|
||||
Z3_ast args[2] = { r, bound };
|
||||
Z3_ast res = Z3_mk_ite(c, pred, Z3_mk_sub(c, 2, args), r);
|
||||
RETURN_Z3(res);
|
||||
}
|
||||
else {
|
||||
expr * _n = to_expr(n);
|
||||
parameter p(to_sort(int_s));
|
||||
ast* a = mk_c(c)->m().mk_app(mk_c(c)->get_bv_fid(), OP_BV2INT, 1, &p, 1, &_n);
|
||||
mk_c(c)->save_ast_trail(a);
|
||||
check_sorts(c, a);
|
||||
RETURN_Z3(of_ast(a));
|
||||
}
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
/**
|
||||
\brief \mlh mk_bvmsb c s \endmlh
|
||||
Create a bit-vector of sort \s with 1 in the most significant bit position.
|
||||
|
||||
The sort \s must be a bit-vector sort.
|
||||
|
||||
This function is a shorthand for <tt>shl(1, N-1)</tt>
|
||||
where <tt>N</tt> are the number of bits of \c s.
|
||||
*/
|
||||
Z3_ast Z3_API Z3_mk_bvmsb(__in Z3_context c, __in Z3_sort s) {
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
// Not logging this one, since it is just syntax sugar.
|
||||
unsigned sz = Z3_get_bv_sort_size(c, s);
|
||||
if (sz == 0) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
return 0;
|
||||
}
|
||||
return Z3_mk_bvshl(c, Z3_mk_int64(c, 1, s), Z3_mk_int64(c, sz - 1, s));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_mk_bvsmin(__in Z3_context c, __in Z3_sort s) {
|
||||
return Z3_mk_bvmsb(c, s);
|
||||
}
|
||||
|
||||
Z3_ast Z3_mk_bvsmax(__in Z3_context c, __in Z3_sort s) {
|
||||
return Z3_mk_bvnot(c, Z3_mk_bvmsb(c, s));
|
||||
}
|
||||
|
||||
Z3_ast Z3_mk_bvumax(__in Z3_context c, __in Z3_sort s) {
|
||||
return Z3_mk_int(c, -1, s);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_mk_bvadd_no_overflow(__in Z3_context c, __in Z3_ast t1, __in Z3_ast t2, Z3_bool is_signed) {
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
if (is_signed) {
|
||||
Z3_ast zero = Z3_mk_int(c, 0, Z3_get_sort(c, t1));
|
||||
Z3_ast r = Z3_mk_bvadd(c, t1, t2);
|
||||
Z3_ast args[2] = { Z3_mk_bvslt(c, zero, t1), Z3_mk_bvslt(c, zero, t2) };
|
||||
Z3_ast args_pos = Z3_mk_and(c, 2, args);
|
||||
return Z3_mk_implies(c, args_pos, Z3_mk_bvslt(c, zero, r));
|
||||
}
|
||||
else {
|
||||
unsigned sz = Z3_get_bv_sort_size(c, Z3_get_sort(c, t1));
|
||||
t1 = Z3_mk_zero_ext(c, 1, t1);
|
||||
t2 = Z3_mk_zero_ext(c, 1, t2);
|
||||
Z3_ast r = Z3_mk_bvadd(c, t1, t2);
|
||||
return Z3_mk_eq(c, Z3_mk_extract(c, sz, sz, r), Z3_mk_int(c, 0, Z3_mk_bv_sort(c, 1)));
|
||||
}
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
// only for signed machine integers
|
||||
Z3_ast Z3_API Z3_mk_bvadd_no_underflow(__in Z3_context c, __in Z3_ast t1, __in Z3_ast t2) {
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
Z3_ast zero = Z3_mk_int(c, 0, Z3_get_sort(c, t1));
|
||||
Z3_ast r = Z3_mk_bvadd(c, t1, t2);
|
||||
Z3_ast args[2] = { Z3_mk_bvslt(c, t1, zero), Z3_mk_bvslt(c, t2, zero) };
|
||||
Z3_ast args_neg = Z3_mk_and(c, 2, args);
|
||||
return Z3_mk_implies(c, args_neg, Z3_mk_bvslt(c, r, zero));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
// only for signed machine integers
|
||||
Z3_ast Z3_API Z3_mk_bvsub_no_overflow(__in Z3_context c, __in Z3_ast t1, __in Z3_ast t2) {
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
Z3_sort s = Z3_get_sort(c, t2);
|
||||
Z3_ast minus_t2 = Z3_mk_bvneg(c, t2);
|
||||
Z3_ast min = Z3_mk_bvsmin(c, s);
|
||||
return Z3_mk_ite(c, Z3_mk_eq(c, t2, min),
|
||||
Z3_mk_bvslt(c, t1, Z3_mk_int(c, 0, s)),
|
||||
Z3_mk_bvadd_no_overflow(c, t1, minus_t2, true));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_mk_bvsub_no_underflow(__in Z3_context c, __in Z3_ast t1, __in Z3_ast t2, Z3_bool is_signed) {
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
if (is_signed) {
|
||||
Z3_ast zero = Z3_mk_int(c, 0, Z3_get_sort(c, t1));
|
||||
if (Z3_get_error_code(c) != Z3_OK) return 0;
|
||||
Z3_ast minus_t2 = Z3_mk_bvneg(c, t2);
|
||||
if (Z3_get_error_code(c) != Z3_OK) return 0;
|
||||
return Z3_mk_implies(c, Z3_mk_bvslt(c, zero, t2), Z3_mk_bvadd_no_underflow(c, t1, minus_t2));
|
||||
}
|
||||
else {
|
||||
return Z3_mk_bvule(c, t2, t1);
|
||||
}
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_mk_bvmul_no_overflow(__in Z3_context c, __in Z3_ast n1, __in Z3_ast n2, Z3_bool is_signed) {
|
||||
LOG_Z3_mk_bvmul_no_overflow(c, n1, n2, is_signed);
|
||||
RESET_ERROR_CODE();
|
||||
if (is_signed) {
|
||||
MK_BINARY_BODY(Z3_mk_bvmul_no_overflow, mk_c(c)->get_bv_fid(), OP_BSMUL_NO_OVFL, SKIP);
|
||||
}
|
||||
else {
|
||||
MK_BINARY_BODY(Z3_mk_bvmul_no_overflow, mk_c(c)->get_bv_fid(), OP_BUMUL_NO_OVFL, SKIP);
|
||||
}
|
||||
}
|
||||
|
||||
// only for signed machine integers
|
||||
Z3_ast Z3_API Z3_mk_bvmul_no_underflow(__in Z3_context c, __in Z3_ast n1, __in Z3_ast n2) {
|
||||
LOG_Z3_mk_bvmul_no_underflow(c, n1, n2);
|
||||
MK_BINARY_BODY(Z3_mk_bvmul_no_underflow, mk_c(c)->get_bv_fid(), OP_BSMUL_NO_UDFL, SKIP);
|
||||
}
|
||||
|
||||
// only for signed machine integers
|
||||
Z3_ast Z3_API Z3_mk_bvneg_no_overflow(__in Z3_context c, __in Z3_ast t) {
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
Z3_ast min = Z3_mk_bvsmin(c, Z3_get_sort(c, t));
|
||||
if (Z3_get_error_code(c) != Z3_OK) return 0;
|
||||
Z3_ast eq = Z3_mk_eq(c, t, min);
|
||||
if (Z3_get_error_code(c) != Z3_OK) return 0;
|
||||
return Z3_mk_not(c, eq);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
// only for signed machine integers
|
||||
Z3_ast Z3_API Z3_mk_bvsdiv_no_overflow(__in Z3_context c, __in Z3_ast t1, __in Z3_ast t2) {
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
Z3_sort s = Z3_get_sort(c, t1);
|
||||
if (Z3_get_error_code(c) != Z3_OK) return 0;
|
||||
Z3_ast min = Z3_mk_bvmsb(c, s);
|
||||
if (Z3_get_error_code(c) != Z3_OK) return 0;
|
||||
Z3_ast args[2] = { Z3_mk_eq(c, t1, min),
|
||||
Z3_mk_eq(c, t2, Z3_mk_int(c, -1, s)) };
|
||||
return Z3_mk_not(c, Z3_mk_and(c, 2, args));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_mk_bvsub(Z3_context c, Z3_ast n1, Z3_ast n2) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_bvsub(c, n1, n2);
|
||||
RESET_ERROR_CODE();
|
||||
// TODO: Do we really need this pre_simplifier hack?
|
||||
if (mk_c(c)->fparams().m_pre_simplify_expr) {
|
||||
Z3_ast m1 = Z3_mk_int(c, -1, Z3_get_sort(c, n2));
|
||||
Z3_ast r = Z3_mk_bvadd(c, n1, Z3_mk_bvmul(c, m1, n2));
|
||||
RETURN_Z3(r);
|
||||
}
|
||||
MK_BINARY_BODY(Z3_mk_bvsub, mk_c(c)->get_bv_fid(), OP_BSUB, SKIP);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_mk_bvneg(Z3_context c, Z3_ast n) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_bvneg(c, n);
|
||||
RESET_ERROR_CODE();
|
||||
// TODO: Do we really need this pre_simplifier hack?
|
||||
if (mk_c(c)->fparams().m_pre_simplify_expr) {
|
||||
Z3_ast m1 = Z3_mk_int(c, -1, Z3_get_sort(c, n));
|
||||
Z3_ast r = Z3_mk_bvmul(c, m1, n);
|
||||
RETURN_Z3(r);
|
||||
}
|
||||
MK_UNARY_BODY(Z3_mk_bvneg, mk_c(c)->get_bv_fid(), OP_BNEG, SKIP);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
unsigned Z3_API Z3_get_bv_sort_size(Z3_context c, Z3_sort t) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_bv_sort_size(c, t);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_VALID_AST(t, 0);
|
||||
if (to_sort(t)->get_family_id() == mk_c(c)->get_bv_fid() && to_sort(t)->get_decl_kind() == BV_SORT) {
|
||||
return to_sort(t)->get_parameter(0).get_int();
|
||||
}
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
return 0;
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
};
|
3525
src/api/api_commands.cpp
Normal file
3525
src/api/api_commands.cpp
Normal file
File diff suppressed because it is too large
Load diff
122
src/api/api_config_params.cpp
Normal file
122
src/api/api_config_params.cpp
Normal file
|
@ -0,0 +1,122 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
api_config_params.cpp
|
||||
|
||||
Abstract:
|
||||
Configuration parameters
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2012-02-29.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include"z3.h"
|
||||
#include"api_context.h"
|
||||
#include"api_config_params.h"
|
||||
#include"pp.h"
|
||||
#include"api_log_macros.h"
|
||||
#include"api_util.h"
|
||||
#include"symbol.h"
|
||||
|
||||
namespace api {
|
||||
|
||||
config_params::config_params():
|
||||
m_ini(false /* do not abort on errors */) {
|
||||
register_verbosity_level(m_ini);
|
||||
register_warning(m_ini);
|
||||
m_params.register_params(m_ini);
|
||||
register_pp_params(m_ini);
|
||||
}
|
||||
|
||||
config_params::config_params(front_end_params const & p):m_params(p) {
|
||||
register_verbosity_level(m_ini);
|
||||
register_warning(m_ini);
|
||||
register_pp_params(m_ini);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
extern std::string smt_keyword2opt_name(symbol const & opt);
|
||||
|
||||
extern "C" {
|
||||
Z3_config Z3_API Z3_mk_config() {
|
||||
LOG_Z3_mk_config();
|
||||
memory::initialize(0);
|
||||
Z3_config r = reinterpret_cast<Z3_config>(alloc(api::config_params));
|
||||
RETURN_Z3(r);
|
||||
}
|
||||
|
||||
void Z3_API Z3_del_config(Z3_config c) {
|
||||
LOG_Z3_del_config(c);
|
||||
dealloc((reinterpret_cast<api::config_params*>(c)));
|
||||
}
|
||||
|
||||
void Z3_API Z3_set_param_value(Z3_config c, char const * param_id, char const * param_value) {
|
||||
try {
|
||||
LOG_Z3_set_param_value(c, param_id, param_value);
|
||||
api::config_params* p = reinterpret_cast<api::config_params*>(c);
|
||||
if (param_id != 0 && param_id[0] == ':') {
|
||||
// Allow SMT2 style paramater names such as :model, :relevancy, etc
|
||||
std::string new_param_id = smt_keyword2opt_name(symbol(param_id));
|
||||
p->m_ini.set_param_value(new_param_id.c_str(), param_value);
|
||||
}
|
||||
else {
|
||||
p->m_ini.set_param_value(param_id, param_value);
|
||||
}
|
||||
}
|
||||
catch (set_get_param_exception & ex) {
|
||||
// The error handler was not set yet.
|
||||
// Just throw a warning.
|
||||
std::ostringstream buffer;
|
||||
buffer << "Error setting " << param_id << ", " << ex.get_msg();
|
||||
warning_msg(buffer.str().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void Z3_API Z3_update_param_value(Z3_context c, Z3_string param_id, Z3_string param_value) {
|
||||
LOG_Z3_update_param_value(c, param_id, param_value);
|
||||
RESET_ERROR_CODE();
|
||||
ini_params ini;
|
||||
mk_c(c)->fparams().register_params(ini);
|
||||
register_pp_params(ini);
|
||||
register_verbosity_level(ini);
|
||||
register_warning(ini);
|
||||
if (mk_c(c)->has_solver()) {
|
||||
ini.freeze();
|
||||
}
|
||||
if (param_id != 0 && param_id[0] == ':') {
|
||||
// Allow SMT2 style paramater names such as :model, :relevancy, etc
|
||||
std::string new_param_id = smt_keyword2opt_name(symbol(param_id));
|
||||
ini.set_param_value(new_param_id.c_str(), param_value);
|
||||
}
|
||||
else {
|
||||
ini.set_param_value(param_id, param_value);
|
||||
}
|
||||
memory::set_high_watermark(static_cast<size_t>(mk_c(c)->fparams().m_memory_high_watermark)*1024*1024);
|
||||
memory::set_max_size(static_cast<size_t>(mk_c(c)->fparams().m_memory_max_size)*1024*1024);
|
||||
}
|
||||
|
||||
Z3_bool Z3_API Z3_get_param_value(Z3_context c, Z3_string param_id, Z3_string* param_value) {
|
||||
LOG_Z3_get_param_value(c, param_id, param_value);
|
||||
ini_params ini;
|
||||
mk_c(c)->fparams().register_params(ini);
|
||||
register_verbosity_level(ini);
|
||||
register_pp_params(ini);
|
||||
register_warning(ini);
|
||||
std::string param_value_s;
|
||||
if (!ini.get_param_value(param_id, param_value_s)) {
|
||||
if (param_value) *param_value = 0;
|
||||
return false;
|
||||
}
|
||||
if (param_value) {
|
||||
*param_value = mk_c(c)->mk_external_string(param_value_s);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
};
|
36
src/api/api_config_params.h
Normal file
36
src/api/api_config_params.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
api_config_params.h
|
||||
|
||||
Abstract:
|
||||
Configuration parameters
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2012-02-29.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _API_CONFIG_PARAMS_H_
|
||||
#define _API_CONFIG_PARAMS_H_
|
||||
|
||||
#include"ini_file.h"
|
||||
#include"front_end_params.h"
|
||||
|
||||
namespace api {
|
||||
|
||||
class config_params {
|
||||
public:
|
||||
ini_params m_ini;
|
||||
front_end_params m_params;
|
||||
config_params();
|
||||
config_params(front_end_params const & p);
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif
|
571
src/api/api_context.cpp
Normal file
571
src/api/api_context.cpp
Normal file
|
@ -0,0 +1,571 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
api_context.cpp
|
||||
|
||||
Abstract:
|
||||
Interface of Z3 with "external world".
|
||||
|
||||
It was called _Z3_context
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2012-02-29.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include"api_context.h"
|
||||
#include"api_config_params.h"
|
||||
#include"smtparser.h"
|
||||
#include"version.h"
|
||||
#include"ast_pp.h"
|
||||
#include"ast_ll_pp.h"
|
||||
#include"api_log_macros.h"
|
||||
#include"api_util.h"
|
||||
#include"install_tactics.h"
|
||||
|
||||
namespace api {
|
||||
|
||||
static void default_error_handler(Z3_context, Z3_error_code c) {
|
||||
printf("Error: %s\n", Z3_get_error_msg(c));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
Z3_search_failure mk_Z3_search_failure(smt::failure f) {
|
||||
switch(f) {
|
||||
case smt::OK: return Z3_NO_FAILURE;
|
||||
case smt::UNKNOWN: return Z3_UNKNOWN;
|
||||
case smt::TIMEOUT: return Z3_TIMEOUT;
|
||||
case smt::MEMOUT: return Z3_MEMOUT_WATERMARK;
|
||||
case smt::CANCELED: return Z3_CANCELED;
|
||||
case smt::NUM_CONFLICTS: return Z3_NUM_CONFLICTS;
|
||||
case smt::THEORY: return Z3_THEORY;
|
||||
case smt::QUANTIFIERS: return Z3_QUANTIFIERS;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
return static_cast<Z3_search_failure>(f);
|
||||
}
|
||||
|
||||
context::param_ini::param_ini(front_end_params & p) : m_params(p) {
|
||||
p.open_trace_file();
|
||||
}
|
||||
|
||||
context::param_ini::~param_ini() {
|
||||
m_params.close_trace_file();
|
||||
}
|
||||
|
||||
context::add_plugins::add_plugins(ast_manager & m) {
|
||||
m.register_decl_plugins();
|
||||
}
|
||||
|
||||
// ------------------------
|
||||
//
|
||||
// Core
|
||||
//
|
||||
// ------------------------
|
||||
|
||||
context::set_interruptable::set_interruptable(context & ctx, event_handler & i):
|
||||
m_ctx(ctx) {
|
||||
#pragma omp critical (set_interruptable)
|
||||
{
|
||||
SASSERT(m_ctx.m_interruptable == 0);
|
||||
m_ctx.m_interruptable = &i;
|
||||
}
|
||||
}
|
||||
|
||||
context::set_interruptable::~set_interruptable() {
|
||||
#pragma omp critical (set_interruptable)
|
||||
{
|
||||
m_ctx.m_interruptable = 0;
|
||||
}
|
||||
}
|
||||
|
||||
context::context(config_params * p, bool user_ref_count):
|
||||
m_params(p ? p->m_params : front_end_params()),
|
||||
m_param_ini(m_params),
|
||||
m_user_ref_count(user_ref_count),
|
||||
m_manager(m_params.m_proof_mode, m_params.m_trace_stream),
|
||||
m_plugins(m_manager),
|
||||
m_arith_util(m_manager),
|
||||
m_bv_util(m_manager),
|
||||
m_datalog_util(m_manager),
|
||||
m_last_result(m_manager),
|
||||
m_ast_trail(m_manager),
|
||||
m_replay_stack() {
|
||||
|
||||
m_solver = 0;
|
||||
m_error_code = Z3_OK;
|
||||
m_print_mode = Z3_PRINT_SMTLIB_FULL;
|
||||
m_searching = false;
|
||||
|
||||
m_interruptable = 0;
|
||||
|
||||
m_smtlib_parser = 0;
|
||||
m_smtlib_parser_has_decls = false;
|
||||
|
||||
z3_bound_num_procs();
|
||||
//
|
||||
// Configuration parameter settings.
|
||||
//
|
||||
memory::set_high_watermark(static_cast<size_t>(m_params.m_memory_high_watermark)*1024*1024);
|
||||
memory::set_max_size(static_cast<size_t>(m_params.m_memory_max_size)*1024*1024);
|
||||
if (m_params.m_debug_ref_count) {
|
||||
m_manager.debug_ref_count();
|
||||
}
|
||||
|
||||
m_error_handler = &default_error_handler;
|
||||
|
||||
m_basic_fid = m_manager.get_basic_family_id();
|
||||
m_arith_fid = m_manager.get_family_id("arith");
|
||||
m_bv_fid = m_manager.get_family_id("bv");
|
||||
m_array_fid = m_manager.get_family_id("array");
|
||||
m_dt_fid = m_manager.get_family_id("datatype");
|
||||
m_datalog_fid = m_manager.get_family_id("datalog_relation");
|
||||
m_dt_plugin = static_cast<datatype_decl_plugin*>(m_manager.get_plugin(m_dt_fid));
|
||||
|
||||
if (!m_user_ref_count) {
|
||||
m_replay_stack.push_back(0);
|
||||
}
|
||||
|
||||
install_tactics(*this);
|
||||
}
|
||||
|
||||
|
||||
context::~context() {
|
||||
m_last_obj = 0;
|
||||
if (!m_user_ref_count) {
|
||||
for (unsigned i = 0; i < m_replay_stack.size(); ++i) {
|
||||
dealloc(m_replay_stack[i]);
|
||||
}
|
||||
}
|
||||
reset_parser();
|
||||
dealloc(m_solver);
|
||||
}
|
||||
|
||||
void context::interrupt() {
|
||||
#pragma omp critical (set_interruptable)
|
||||
{
|
||||
if (m_interruptable)
|
||||
(*m_interruptable)();
|
||||
}
|
||||
}
|
||||
|
||||
void context::set_error_code(Z3_error_code err) {
|
||||
m_error_code = err;
|
||||
if (err != Z3_OK)
|
||||
invoke_error_handler(err);
|
||||
}
|
||||
|
||||
void context::check_searching() {
|
||||
if (m_searching) {
|
||||
set_error_code(Z3_INVALID_USAGE); // TBD: error code could be fixed.
|
||||
}
|
||||
}
|
||||
|
||||
char * context::mk_external_string(char const * str) {
|
||||
m_string_buffer = str;
|
||||
return const_cast<char *>(m_string_buffer.c_str());
|
||||
}
|
||||
|
||||
char * context::mk_external_string(std::string const & str) {
|
||||
m_string_buffer = str;
|
||||
return const_cast<char *>(m_string_buffer.c_str());
|
||||
}
|
||||
|
||||
expr * context::mk_numeral_core(rational const & n, sort * s) {
|
||||
expr* e = 0;
|
||||
family_id fid = s->get_family_id();
|
||||
if (fid == m_arith_fid) {
|
||||
e = m_arith_util.mk_numeral(n, s);
|
||||
}
|
||||
else if (fid == m_bv_fid) {
|
||||
e = m_bv_util.mk_numeral(n, s);
|
||||
}
|
||||
else if (fid == get_datalog_fid() && n.is_uint64()) {
|
||||
uint64 sz;
|
||||
if (m_datalog_util.try_get_size(s, sz) &&
|
||||
sz <= n.get_uint64()) {
|
||||
invoke_error_handler(Z3_INVALID_ARG);
|
||||
}
|
||||
e = m_datalog_util.mk_numeral(n.get_uint64(), s);
|
||||
}
|
||||
else {
|
||||
invoke_error_handler(Z3_INVALID_ARG);
|
||||
}
|
||||
save_ast_trail(e);
|
||||
return e;
|
||||
}
|
||||
|
||||
expr * context::mk_and(unsigned num_exprs, expr * const * exprs) {
|
||||
switch(num_exprs) {
|
||||
case 0:
|
||||
return m_manager.mk_true();
|
||||
case 1:
|
||||
save_ast_trail(exprs[0]);
|
||||
return exprs[0];
|
||||
default: {
|
||||
expr * a = m_manager.mk_and(num_exprs, exprs);
|
||||
save_ast_trail(a);
|
||||
return a;
|
||||
} }
|
||||
}
|
||||
|
||||
void context::persist_ast(ast * n, unsigned num_scopes) {
|
||||
// persist_ast is irrelevant when m_user_ref_count == true
|
||||
if (m_user_ref_count)
|
||||
return;
|
||||
if (num_scopes > m_ast_lim.size()) {
|
||||
num_scopes = m_ast_lim.size();
|
||||
}
|
||||
SASSERT(m_replay_stack.size() > num_scopes);
|
||||
unsigned j = m_replay_stack.size() - num_scopes - 1;
|
||||
if (!m_replay_stack[j]) {
|
||||
m_replay_stack[j] = alloc(ast_ref_vector, m_manager);
|
||||
}
|
||||
m_replay_stack[j]->push_back(n);
|
||||
}
|
||||
|
||||
void context::save_ast_trail(ast * n) {
|
||||
SASSERT(m().contains(n));
|
||||
if (m_user_ref_count) {
|
||||
// Corner case bug: n may be in m_last_result, and this is the only reference to n.
|
||||
// When, we execute reset() it is deleted
|
||||
// To avoid this bug, I bump the reference counter before reseting m_last_result
|
||||
m().inc_ref(n);
|
||||
m_last_result.reset();
|
||||
m_last_result.push_back(n);
|
||||
m().dec_ref(n);
|
||||
}
|
||||
else {
|
||||
m_ast_trail.push_back(n);
|
||||
}
|
||||
}
|
||||
|
||||
void context::save_multiple_ast_trail(ast * n) {
|
||||
if (m_user_ref_count)
|
||||
m_last_result.push_back(n);
|
||||
else
|
||||
m_ast_trail.push_back(n);
|
||||
}
|
||||
|
||||
void context::reset_last_result() {
|
||||
if (m_user_ref_count)
|
||||
m_last_result.reset();
|
||||
m_last_obj = 0;
|
||||
}
|
||||
|
||||
void context::save_object(object * r) {
|
||||
m_last_obj = r;
|
||||
}
|
||||
|
||||
void context::handle_exception(z3_exception & ex) {
|
||||
if (ex.has_error_code()) {
|
||||
switch(ex.error_code()) {
|
||||
case ERR_MEMOUT:
|
||||
set_error_code(Z3_MEMOUT_FAIL);
|
||||
break;
|
||||
case ERR_PARSER:
|
||||
set_error_code(Z3_PARSER_ERROR);
|
||||
break;
|
||||
case ERR_INI_FILE:
|
||||
set_error_code(Z3_INVALID_ARG);
|
||||
break;
|
||||
case ERR_OPEN_FILE:
|
||||
set_error_code(Z3_FILE_ACCESS_ERROR);
|
||||
break;
|
||||
default:
|
||||
set_error_code(Z3_INTERNAL_FATAL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
m_exception_msg = ex.msg();
|
||||
set_error_code(Z3_EXCEPTION);
|
||||
}
|
||||
}
|
||||
|
||||
void context::invoke_error_handler(Z3_error_code c) {
|
||||
if (m_error_handler) {
|
||||
if (g_z3_log) {
|
||||
// error handler can do crazy stuff such as longjmp
|
||||
g_z3_log_enabled = true;
|
||||
}
|
||||
m_error_handler(reinterpret_cast<Z3_context>(this), c);
|
||||
}
|
||||
}
|
||||
|
||||
void context::check_sorts(ast * n) {
|
||||
if (!m().check_sorts(n)) {
|
||||
switch(n->get_kind()) {
|
||||
case AST_APP: {
|
||||
std::ostringstream buffer;
|
||||
app * a = to_app(n);
|
||||
buffer << mk_pp(a->get_decl(), m()) << " applied to: ";
|
||||
if (a->get_num_args() > 1) buffer << "\n";
|
||||
for (unsigned i = 0; i < a->get_num_args(); ++i) {
|
||||
buffer << mk_bounded_pp(a->get_arg(i), m(), 3) << " of sort ";
|
||||
buffer << mk_pp(m().get_sort(a->get_arg(i)), m()) << "\n";
|
||||
}
|
||||
warning_msg("%s",buffer.str().c_str());
|
||||
break;
|
||||
}
|
||||
case AST_VAR:
|
||||
case AST_QUANTIFIER:
|
||||
case AST_SORT:
|
||||
case AST_FUNC_DECL:
|
||||
break;
|
||||
}
|
||||
set_error_code(Z3_SORT_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------
|
||||
//
|
||||
// Solver interface for backward compatibility
|
||||
//
|
||||
// ------------------------
|
||||
|
||||
smt::solver & context::get_solver() {
|
||||
if (!m_solver) {
|
||||
m_solver = alloc(smt::solver, m_manager, m_params);
|
||||
}
|
||||
return *m_solver;
|
||||
}
|
||||
|
||||
void context::assert_cnstr(expr * a) {
|
||||
get_solver().assert_expr(a);
|
||||
}
|
||||
|
||||
lbool context::check(model_ref & m) {
|
||||
flet<bool> searching(m_searching, true);
|
||||
lbool r;
|
||||
r = get_solver().check();
|
||||
if (r != l_false)
|
||||
get_solver().get_model(m);
|
||||
return r;
|
||||
}
|
||||
|
||||
void context::push() {
|
||||
get_solver().push();
|
||||
if (!m_user_ref_count) {
|
||||
m_ast_lim.push_back(m_ast_trail.size());
|
||||
m_replay_stack.push_back(0);
|
||||
}
|
||||
}
|
||||
|
||||
void context::pop(unsigned num_scopes) {
|
||||
for (unsigned i = 0; i < num_scopes; ++i) {
|
||||
if (!m_user_ref_count) {
|
||||
unsigned sz = m_ast_lim.back();
|
||||
m_ast_lim.pop_back();
|
||||
dealloc(m_replay_stack.back());
|
||||
m_replay_stack.pop_back();
|
||||
while (m_ast_trail.size() > sz) {
|
||||
m_ast_trail.pop_back();
|
||||
}
|
||||
}
|
||||
}
|
||||
get_solver().pop(num_scopes);
|
||||
}
|
||||
|
||||
// ------------------------
|
||||
//
|
||||
// Parser interface for backward compatibility
|
||||
//
|
||||
// ------------------------
|
||||
|
||||
void context::reset_parser() {
|
||||
if (m_smtlib_parser) {
|
||||
dealloc(m_smtlib_parser);
|
||||
m_smtlib_parser = 0;
|
||||
m_smtlib_parser_has_decls = false;
|
||||
m_smtlib_parser_decls.reset();
|
||||
m_smtlib_parser_sorts.reset();
|
||||
}
|
||||
SASSERT(!m_smtlib_parser_has_decls);
|
||||
}
|
||||
|
||||
void context::extract_smtlib_parser_decls() {
|
||||
if (m_smtlib_parser) {
|
||||
if (!m_smtlib_parser_has_decls) {
|
||||
smtlib::symtable * table = m_smtlib_parser->get_benchmark()->get_symtable();
|
||||
table->get_func_decls(m_smtlib_parser_decls);
|
||||
table->get_sorts(m_smtlib_parser_sorts);
|
||||
m_smtlib_parser_has_decls = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
m_smtlib_parser_decls.reset();
|
||||
m_smtlib_parser_sorts.reset();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// ------------------------
|
||||
//
|
||||
// Context creation API
|
||||
//
|
||||
// ------------------------
|
||||
|
||||
extern "C" {
|
||||
|
||||
Z3_context Z3_API Z3_mk_context(Z3_config c) {
|
||||
LOG_Z3_mk_context(c);
|
||||
memory::initialize(0);
|
||||
Z3_context r = reinterpret_cast<Z3_context>(alloc(api::context, reinterpret_cast<api::config_params*>(c), false));
|
||||
RETURN_Z3(r);
|
||||
}
|
||||
|
||||
Z3_context Z3_API Z3_mk_context_rc(Z3_config c) {
|
||||
LOG_Z3_mk_context_rc(c);
|
||||
memory::initialize(0);
|
||||
Z3_context r = reinterpret_cast<Z3_context>(alloc(api::context, reinterpret_cast<api::config_params*>(c), true));
|
||||
RETURN_Z3(r);
|
||||
}
|
||||
|
||||
void Z3_API Z3_del_context(Z3_context c) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_del_context(c);
|
||||
RESET_ERROR_CODE();
|
||||
dealloc(mk_c(c));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_interrupt(Z3_context c) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_interrupt(c);
|
||||
mk_c(c)->interrupt();
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_toggle_warning_messages(Z3_bool enabled) {
|
||||
LOG_Z3_toggle_warning_messages(enabled);
|
||||
enable_warning_messages(enabled != 0);
|
||||
}
|
||||
|
||||
void Z3_API Z3_inc_ref(Z3_context c, Z3_ast a) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_inc_ref(c, a);
|
||||
RESET_ERROR_CODE();
|
||||
mk_c(c)->m().inc_ref(to_ast(a));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_dec_ref(Z3_context c, Z3_ast a) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_dec_ref(c, a);
|
||||
RESET_ERROR_CODE();
|
||||
if (to_ast(a)->get_ref_count() == 0) {
|
||||
SET_ERROR_CODE(Z3_DEC_REF_ERROR);
|
||||
return;
|
||||
}
|
||||
mk_c(c)->m().dec_ref(to_ast(a));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
Z3_bool Z3_API Z3_set_logic(Z3_context c, Z3_string logic) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_set_logic(c, logic);
|
||||
RESET_ERROR_CODE();
|
||||
return mk_c(c)->get_solver().set_logic(symbol(logic));
|
||||
Z3_CATCH_RETURN(Z3_FALSE);
|
||||
}
|
||||
|
||||
void Z3_API Z3_get_version(unsigned * major,
|
||||
unsigned * minor,
|
||||
unsigned * build_number,
|
||||
unsigned * revision_number) {
|
||||
LOG_Z3_get_version(major, minor, build_number, revision_number);
|
||||
*major = Z3_MAJOR_VERSION;
|
||||
*minor = Z3_MINOR_VERSION;
|
||||
*build_number = Z3_BUILD_NUMBER;
|
||||
*revision_number = Z3_REVISION_NUMBER;
|
||||
}
|
||||
|
||||
void Z3_API Z3_reset_memory(void) {
|
||||
LOG_Z3_reset_memory();
|
||||
memory::finalize();
|
||||
memory::initialize(0);
|
||||
}
|
||||
|
||||
Z3_error_code Z3_API Z3_get_error_code(Z3_context c) {
|
||||
LOG_Z3_get_error_code(c);
|
||||
return mk_c(c)->get_error_code();
|
||||
}
|
||||
|
||||
void Z3_API Z3_set_error_handler(Z3_context c, Z3_error_handler h) {
|
||||
RESET_ERROR_CODE();
|
||||
mk_c(c)->set_error_handler(h);
|
||||
// [Leo]: using exception handling, we don't need global error handlers anymore
|
||||
}
|
||||
|
||||
void Z3_API Z3_set_error(__in Z3_context c, __in Z3_error_code e) {
|
||||
SET_ERROR_CODE(e);
|
||||
}
|
||||
|
||||
static char const * _get_error_msg_ex(Z3_context c, Z3_error_code err) {
|
||||
switch(err) {
|
||||
case Z3_OK: return "ok";
|
||||
case Z3_SORT_ERROR: return "type error";
|
||||
case Z3_IOB: return "index out of bounds";
|
||||
case Z3_INVALID_ARG: return "invalid argument";
|
||||
case Z3_PARSER_ERROR: return "parser error";
|
||||
case Z3_NO_PARSER: return "parser (data) is not available";
|
||||
case Z3_INVALID_PATTERN: return "invalid pattern";
|
||||
case Z3_MEMOUT_FAIL: return "out of memory";
|
||||
case Z3_FILE_ACCESS_ERROR: return "file access error";
|
||||
case Z3_INTERNAL_FATAL: return "internal error";
|
||||
case Z3_INVALID_USAGE: return "invalid usage";
|
||||
case Z3_DEC_REF_ERROR: return "invalid dec_ref command";
|
||||
case Z3_EXCEPTION: return c == 0 ? "Z3 exception" : mk_c(c)->get_exception_msg();
|
||||
default: return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
char const * Z3_API Z3_get_error_msg(Z3_error_code err) {
|
||||
LOG_Z3_get_error_msg(err);
|
||||
return _get_error_msg_ex(0, err);
|
||||
}
|
||||
|
||||
char const * Z3_API Z3_get_error_msg_ex(Z3_context c, Z3_error_code err) {
|
||||
LOG_Z3_get_error_msg_ex(c, err);
|
||||
return _get_error_msg_ex(c, err);
|
||||
}
|
||||
|
||||
void Z3_API Z3_persist_ast(Z3_context c, Z3_ast n, unsigned num_scopes) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_persist_ast(c, n, num_scopes);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_VALID_AST(to_ast(n), );
|
||||
mk_c(c)->persist_ast(to_ast(n), num_scopes);
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_set_ast_print_mode(Z3_context c, Z3_ast_print_mode mode) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_set_ast_print_mode(c, mode);
|
||||
RESET_ERROR_CODE();
|
||||
mk_c(c)->set_print_mode(mode);
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
ast_manager & Z3_API Z3_get_manager(__in Z3_context c) {
|
||||
return mk_c(c)->m();
|
||||
}
|
||||
|
||||
front_end_params& Z3_API Z3_get_parameters(__in Z3_context c) {
|
||||
return mk_c(c)->fparams();
|
||||
}
|
||||
|
||||
Z3_context Z3_mk_context_from_params(front_end_params const& p) {
|
||||
api::config_params cp(p);
|
||||
return reinterpret_cast<Z3_context>(alloc(api::context, &cp));
|
||||
}
|
216
src/api/api_context.h
Normal file
216
src/api/api_context.h
Normal file
|
@ -0,0 +1,216 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
api_context.h
|
||||
|
||||
Abstract:
|
||||
Interface of Z3 with "external world".
|
||||
|
||||
It was called _Z3_context
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2012-02-29.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _API_CONTEXT_H_
|
||||
#define _API_CONTEXT_H_
|
||||
|
||||
#include"z3.h"
|
||||
#include"ast.h"
|
||||
#include"api_util.h"
|
||||
#include"arith_decl_plugin.h"
|
||||
#include"bv_decl_plugin.h"
|
||||
#include"datatype_decl_plugin.h"
|
||||
#include"dl_decl_plugin.h"
|
||||
#include"smt_solver.h"
|
||||
#include"front_end_params.h"
|
||||
#include"event_handler.h"
|
||||
#include"tactic_manager.h"
|
||||
|
||||
namespace smtlib {
|
||||
class parser;
|
||||
};
|
||||
|
||||
namespace api {
|
||||
class config_params;
|
||||
|
||||
Z3_search_failure mk_Z3_search_failure(smt::failure f);
|
||||
|
||||
|
||||
class context : public tactic_manager {
|
||||
class param_ini {
|
||||
front_end_params & m_params;
|
||||
public:
|
||||
param_ini(front_end_params & p);
|
||||
~param_ini();
|
||||
};
|
||||
|
||||
struct add_plugins { add_plugins(ast_manager & m); };
|
||||
|
||||
front_end_params m_params;
|
||||
param_ini m_param_ini;
|
||||
bool m_user_ref_count; //!< if true, the user is responsible for managing referenc counters.
|
||||
ast_manager m_manager;
|
||||
add_plugins m_plugins;
|
||||
|
||||
arith_util m_arith_util;
|
||||
bv_util m_bv_util;
|
||||
datalog::dl_decl_util m_datalog_util;
|
||||
|
||||
smt::solver * m_solver; // General purpose solver for backward compatibility
|
||||
|
||||
ast_ref_vector m_last_result; //!< used when m_user_ref_count == true
|
||||
ast_ref_vector m_ast_trail; //!< used when m_user_ref_count == false
|
||||
unsigned_vector m_ast_lim;
|
||||
ptr_vector<ast_ref_vector> m_replay_stack;
|
||||
|
||||
ref<api::object> m_last_obj; //!< reference to the last API object returned by the APIs
|
||||
|
||||
family_id m_basic_fid;
|
||||
family_id m_array_fid;
|
||||
family_id m_arith_fid;
|
||||
family_id m_bv_fid;
|
||||
family_id m_dt_fid;
|
||||
family_id m_datalog_fid;
|
||||
datatype_decl_plugin * m_dt_plugin;
|
||||
|
||||
std::string m_string_buffer; // temporary buffer used to cache strings sent to the "external" world.
|
||||
|
||||
Z3_error_code m_error_code;
|
||||
Z3_error_handler * m_error_handler;
|
||||
std::string m_exception_msg; // catch the message associated with a Z3 exception
|
||||
bool m_searching;
|
||||
Z3_ast_print_mode m_print_mode;
|
||||
|
||||
event_handler * m_interruptable; // Reference to an object that can be interrupted by Z3_interrupt
|
||||
public:
|
||||
// Scoped obj for setting m_interruptable
|
||||
class set_interruptable {
|
||||
context & m_ctx;
|
||||
public:
|
||||
set_interruptable(context & ctx, event_handler & i);
|
||||
~set_interruptable();
|
||||
};
|
||||
|
||||
// ------------------------
|
||||
//
|
||||
// Core
|
||||
//
|
||||
// ------------------------
|
||||
|
||||
context(config_params * p, bool user_ref_count = false);
|
||||
~context();
|
||||
|
||||
front_end_params & fparams() { return m_params; }
|
||||
ast_manager & m() { return m_manager; }
|
||||
arith_util & autil() { return m_arith_util; }
|
||||
bv_util & bvutil() { return m_bv_util; }
|
||||
datalog::dl_decl_util & datalog_util() { return m_datalog_util; }
|
||||
family_id get_basic_fid() const { return m_basic_fid; }
|
||||
family_id get_array_fid() const { return m_array_fid; }
|
||||
family_id get_arith_fid() const { return m_arith_fid; }
|
||||
family_id get_bv_fid() const { return m_bv_fid; }
|
||||
family_id get_dt_fid() const { return m_dt_fid; }
|
||||
family_id get_datalog_fid() const { return m_datalog_fid; }
|
||||
datatype_decl_plugin * get_dt_plugin() const { return m_dt_plugin; }
|
||||
|
||||
Z3_error_code get_error_code() const { return m_error_code; }
|
||||
void reset_error_code() { m_error_code = Z3_OK; }
|
||||
void set_error_code(Z3_error_code err);
|
||||
void set_error_handler(Z3_error_handler h) { m_error_handler = h; }
|
||||
// Sign an error if solver is searching
|
||||
void check_searching();
|
||||
|
||||
Z3_ast_print_mode get_print_mode() const { return m_print_mode; }
|
||||
void set_print_mode(Z3_ast_print_mode m) { m_print_mode = m; }
|
||||
|
||||
// Store a copy of str in m_string_buffer, and return a reference to it.
|
||||
// This method is used to communicate local/internal strings with the "external world"
|
||||
char * mk_external_string(char const * str);
|
||||
char * mk_external_string(std::string const & str);
|
||||
|
||||
// Create a numeral of the given sort
|
||||
expr * mk_numeral_core(rational const & n, sort * s);
|
||||
|
||||
// Return a conjuction that will be exposed to the "external" world.
|
||||
expr * mk_and(unsigned num_exprs, expr * const * exprs);
|
||||
|
||||
// Hack for preventing an AST for being GC when ref-count is not used
|
||||
void persist_ast(ast * n, unsigned num_scopes);
|
||||
|
||||
// "Save" an AST that will exposed to the "external" world.
|
||||
void save_ast_trail(ast * n);
|
||||
|
||||
// Similar to previous method, but it "adds" n to the result.
|
||||
void save_multiple_ast_trail(ast * n);
|
||||
|
||||
// Reset the cache that stores the ASTs exposed in the previous call.
|
||||
// This is a NOOP if ref-count is disabled.
|
||||
void reset_last_result();
|
||||
|
||||
// "Save" a reference to an object that is exposed by the API
|
||||
void save_object(object * r);
|
||||
|
||||
// Process exception: save message and set error code.
|
||||
void handle_exception(z3_exception & ex);
|
||||
char const * get_exception_msg() const { return m_exception_msg.c_str(); }
|
||||
|
||||
// Interrupt the current interruptable object
|
||||
void interrupt();
|
||||
|
||||
void invoke_error_handler(Z3_error_code c);
|
||||
|
||||
static void out_of_memory_handler(void * _ctx);
|
||||
|
||||
void check_sorts(ast * n);
|
||||
// ------------------------
|
||||
//
|
||||
// Solver interface for backward compatibility
|
||||
//
|
||||
// ------------------------
|
||||
|
||||
bool has_solver() const { return m_solver != 0; }
|
||||
smt::solver & get_solver();
|
||||
void assert_cnstr(expr * a);
|
||||
lbool check(model_ref & m);
|
||||
void push();
|
||||
void pop(unsigned num_scopes);
|
||||
unsigned get_num_scopes() const { return m_ast_lim.size(); }
|
||||
|
||||
// ------------------------
|
||||
//
|
||||
// Parser interface for backward compatibility
|
||||
//
|
||||
// ------------------------
|
||||
|
||||
// TODO: move to a "parser" object visible to the external world.
|
||||
std::string m_smtlib_error_buffer;
|
||||
smtlib::parser * m_smtlib_parser;
|
||||
bool m_smtlib_parser_has_decls;
|
||||
ptr_vector<func_decl> m_smtlib_parser_decls;
|
||||
ptr_vector<sort> m_smtlib_parser_sorts;
|
||||
|
||||
void reset_parser();
|
||||
void extract_smtlib_parser_decls();
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
inline api::context * mk_c(Z3_context c) { return reinterpret_cast<api::context*>(c); }
|
||||
#define RESET_ERROR_CODE() { mk_c(c)->reset_error_code(); }
|
||||
#define SET_ERROR_CODE(ERR) { mk_c(c)->set_error_code(ERR); }
|
||||
#define CHECK_NON_NULL(_p_,_ret_) { if (_p_ == 0) { SET_ERROR_CODE(Z3_INVALID_ARG); return _ret_; } }
|
||||
#define CHECK_VALID_AST(_a_, _ret_) { if (_a_ == 0 || !CHECK_REF_COUNT(_a_)) { SET_ERROR_CODE(Z3_INVALID_ARG); return _ret_; } }
|
||||
#define CHECK_SEARCHING(c) mk_c(c)->check_searching();
|
||||
inline bool is_expr(Z3_ast a) { return is_expr(to_ast(a)); }
|
||||
inline bool is_bool_expr(Z3_context c, Z3_ast a) { return is_expr(a) && mk_c(c)->m().is_bool(to_expr(a)); }
|
||||
#define CHECK_FORMULA(_a_, _ret_) { if (_a_ == 0 || !CHECK_REF_COUNT(_a_) || !is_bool_expr(c, _a_)) { SET_ERROR_CODE(Z3_INVALID_ARG); return _ret_; } }
|
||||
inline void check_sorts(Z3_context c, ast * n) { mk_c(c)->check_sorts(n); }
|
||||
|
||||
#endif
|
561
src/api/api_datalog.cpp
Normal file
561
src/api/api_datalog.cpp
Normal file
|
@ -0,0 +1,561 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
api_datalog.cpp
|
||||
|
||||
Abstract:
|
||||
Datalog API
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2012-02-29.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include"api_datalog.h"
|
||||
#include"api_context.h"
|
||||
#include"api_util.h"
|
||||
#include"dl_context.h"
|
||||
#include"ast_pp.h"
|
||||
#include"api_ast_vector.h"
|
||||
#include"api_log_macros.h"
|
||||
#include"api_stats.h"
|
||||
#include"datalog_parser.h"
|
||||
#include"cancel_eh.h"
|
||||
#include"scoped_timer.h"
|
||||
|
||||
namespace api {
|
||||
|
||||
fixedpoint_context::fixedpoint_context(ast_manager& m, front_end_params& p) :
|
||||
m_state(0),
|
||||
m_reduce_app(0),
|
||||
m_reduce_assign(0),
|
||||
m_context(m, p),
|
||||
m_trail(m) {}
|
||||
|
||||
|
||||
void fixedpoint_context::set_state(void* state) {
|
||||
SASSERT(!m_state);
|
||||
m_state = state;
|
||||
symbol name("datalog_relation");
|
||||
ast_manager& m = m_context.get_manager();
|
||||
if (!m.has_plugin(name)) {
|
||||
m.register_plugin(name, alloc(datalog::dl_decl_plugin));
|
||||
}
|
||||
datalog::relation_manager& r = m_context.get_rmanager();
|
||||
r.register_plugin(alloc(datalog::external_relation_plugin, *this, r));
|
||||
}
|
||||
|
||||
void fixedpoint_context::reduce(func_decl* f, unsigned num_args, expr * const* args, expr_ref& result) {
|
||||
expr* r = 0;
|
||||
if (m_reduce_app) {
|
||||
m_reduce_app(m_state, f, num_args, args, &r);
|
||||
result = r;
|
||||
m_trail.push_back(f);
|
||||
for (unsigned i = 0; i < num_args; ++i) {
|
||||
m_trail.push_back(args[i]);
|
||||
}
|
||||
m_trail.push_back(r);
|
||||
}
|
||||
// allow fallthrough.
|
||||
if (r == 0) {
|
||||
ast_manager& m = m_context.get_manager();
|
||||
result = m.mk_app(f, num_args, args);
|
||||
}
|
||||
}
|
||||
|
||||
// overwrite terms passed in outs vector with values computed by function.
|
||||
void fixedpoint_context::reduce_assign(func_decl* f, unsigned num_args, expr * const* args, unsigned num_out, expr* const* outs) {
|
||||
if (m_reduce_assign) {
|
||||
m_trail.push_back(f);
|
||||
for (unsigned i = 0; i < num_args; ++i) {
|
||||
m_trail.push_back(args[i]);
|
||||
}
|
||||
m_reduce_assign(m_state, f, num_args, args, num_out, outs);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void fixedpoint_context::add_rule(expr* rule, symbol const& name) {
|
||||
m_context.add_rule(rule, name);
|
||||
}
|
||||
|
||||
void fixedpoint_context::update_rule(expr* rule, symbol const& name) {
|
||||
m_context.update_rule(rule, name);
|
||||
}
|
||||
|
||||
void fixedpoint_context::add_table_fact(func_decl* r, unsigned num_args, unsigned args[]) {
|
||||
m_context.add_table_fact(r, num_args, args);
|
||||
}
|
||||
|
||||
unsigned fixedpoint_context::get_num_levels(func_decl* pred) {
|
||||
return m_context.get_num_levels(pred);
|
||||
}
|
||||
|
||||
expr_ref fixedpoint_context::get_cover_delta(int level, func_decl* pred) {
|
||||
return m_context.get_cover_delta(level, pred);
|
||||
}
|
||||
|
||||
void fixedpoint_context::add_cover(int level, func_decl* pred, expr* predicate) {
|
||||
m_context.add_cover(level, pred, predicate);
|
||||
}
|
||||
|
||||
std::string fixedpoint_context::get_last_status() {
|
||||
datalog::execution_result status = m_context.get_status();
|
||||
switch(status) {
|
||||
case datalog::INPUT_ERROR:
|
||||
return "input error";
|
||||
case datalog::OK:
|
||||
return "ok";
|
||||
case datalog::TIMEOUT:
|
||||
return "timeout";
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
std::string fixedpoint_context::to_string(unsigned num_queries, expr*const* queries) {
|
||||
std::stringstream str;
|
||||
m_context.display_smt2(num_queries, queries, str);
|
||||
return str.str();
|
||||
}
|
||||
|
||||
void fixedpoint_context::simplify_rules(
|
||||
unsigned num_rules, expr* const* rules,
|
||||
unsigned num_outputs, func_decl* const* outputs, expr_ref_vector& result) {
|
||||
ast_manager& m = m_context.get_manager();
|
||||
|
||||
datalog::context ctx(m, m_context.get_fparams());
|
||||
datalog::rule_manager& rm = ctx.get_rule_manager();
|
||||
for (unsigned i = 0; i < num_rules; ++i) {
|
||||
expr* rule = rules[i], *body, *head;
|
||||
while (true) {
|
||||
if (is_quantifier(rule)) {
|
||||
rule = to_quantifier(rule)->get_expr();
|
||||
}
|
||||
else if (m.is_implies(rule, body, head)) {
|
||||
rule = head;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (is_app(rule)) {
|
||||
func_decl* r = to_app(rule)->get_decl();
|
||||
if (!ctx.is_predicate(r)) {
|
||||
ctx.register_predicate(r);
|
||||
if (num_outputs == 0) {
|
||||
ctx.set_output_predicate(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (unsigned i = 0; i < num_outputs; ++i) {
|
||||
ctx.set_output_predicate(outputs[i]);
|
||||
}
|
||||
for (unsigned i = 0; i < num_rules; ++i) {
|
||||
expr* rule = rules[i];
|
||||
ctx.add_rule(rule, symbol::null);
|
||||
}
|
||||
model_converter_ref mc; // not exposed.
|
||||
proof_converter_ref pc; // not exposed.
|
||||
ctx.apply_default_transformation(mc, pc);
|
||||
datalog::rule_set const& new_rules = ctx.get_rules();
|
||||
datalog::rule_set::iterator it = new_rules.begin(), end = new_rules.end();
|
||||
for (; it != end; ++it) {
|
||||
datalog::rule* r = *it;
|
||||
expr_ref fml(m);
|
||||
r->to_formula(fml);
|
||||
result.push_back(fml);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
extern "C" {
|
||||
|
||||
////////////////////////////////////
|
||||
// Datalog utilities
|
||||
//
|
||||
|
||||
|
||||
unsigned Z3_API Z3_get_relation_arity(Z3_context c, Z3_sort s) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_relation_arity(c, s);
|
||||
RESET_ERROR_CODE();
|
||||
sort * r = to_sort(s);
|
||||
if (Z3_get_sort_kind(c, s) != Z3_RELATION_SORT) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
return 0;
|
||||
}
|
||||
return r->get_num_parameters();
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_sort Z3_API Z3_get_relation_column(Z3_context c, Z3_sort s, unsigned col) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_relation_column(c, s, col);
|
||||
RESET_ERROR_CODE();
|
||||
sort * r = to_sort(s);
|
||||
if (Z3_get_sort_kind(c, s) != Z3_RELATION_SORT) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
if (col >= r->get_num_parameters()) {
|
||||
SET_ERROR_CODE(Z3_IOB);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
parameter const& p = r->get_parameter(col);
|
||||
if (!p.is_ast() || !is_sort(p.get_ast())) {
|
||||
UNREACHABLE();
|
||||
warning_msg("Sort parameter expected at %d", col);
|
||||
SET_ERROR_CODE(Z3_INTERNAL_FATAL);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
Z3_sort res = of_sort(to_sort(p.get_ast()));
|
||||
RETURN_Z3(res);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_sort Z3_API Z3_mk_finite_domain_sort(Z3_context c, Z3_symbol name, unsigned __int64 size) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_finite_domain_sort(c, name, size);
|
||||
RESET_ERROR_CODE();
|
||||
sort* s = mk_c(c)->datalog_util().mk_sort(to_symbol(name), size);
|
||||
mk_c(c)->save_ast_trail(s);
|
||||
RETURN_Z3(of_sort(s));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_bool Z3_API Z3_get_finite_domain_sort_size(Z3_context c, Z3_sort s, unsigned __int64 * out) {
|
||||
Z3_TRY;
|
||||
if (out) {
|
||||
*out = 0;
|
||||
}
|
||||
if (Z3_get_sort_kind(c, s) != Z3_FINITE_DOMAIN_SORT) {
|
||||
return Z3_FALSE;
|
||||
}
|
||||
if (!out) {
|
||||
return Z3_FALSE;
|
||||
}
|
||||
// must start loggging here, since function uses Z3_get_sort_kind above
|
||||
LOG_Z3_get_finite_domain_sort_size(c, s, out);
|
||||
RESET_ERROR_CODE();
|
||||
VERIFY(mk_c(c)->datalog_util().try_get_size(to_sort(s), *out));
|
||||
return Z3_TRUE;
|
||||
|
||||
Z3_CATCH_RETURN(Z3_FALSE);
|
||||
}
|
||||
|
||||
Z3_fixedpoint Z3_API Z3_mk_fixedpoint(Z3_context c) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_fixedpoint(c);
|
||||
RESET_ERROR_CODE();
|
||||
Z3_fixedpoint_ref * d = alloc(Z3_fixedpoint_ref);
|
||||
d->m_datalog = alloc(api::fixedpoint_context, mk_c(c)->m(), mk_c(c)->fparams());
|
||||
mk_c(c)->save_object(d);
|
||||
Z3_fixedpoint r = of_datalog(d);
|
||||
RETURN_Z3(r);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
void Z3_API Z3_fixedpoint_inc_ref(Z3_context c, Z3_fixedpoint s) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_fixedpoint_inc_ref(c, s);
|
||||
RESET_ERROR_CODE();
|
||||
to_fixedpoint(s)->inc_ref();
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_fixedpoint_dec_ref(Z3_context c, Z3_fixedpoint s) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_fixedpoint_dec_ref(c, s);
|
||||
RESET_ERROR_CODE();
|
||||
to_fixedpoint(s)->dec_ref();
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_fixedpoint_assert(Z3_context c, Z3_fixedpoint d, Z3_ast a) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_fixedpoint_assert(c, d, a);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_FORMULA(a,);
|
||||
to_fixedpoint_ref(d)->ctx().assert_expr(to_expr(a));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_fixedpoint_add_rule(Z3_context c, Z3_fixedpoint d, Z3_ast a, Z3_symbol name) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_fixedpoint_add_rule(c, d, a, name);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_FORMULA(a,);
|
||||
to_fixedpoint_ref(d)->add_rule(to_expr(a), to_symbol(name));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_fixedpoint_add_fact(Z3_context c, Z3_fixedpoint d,
|
||||
Z3_func_decl r, unsigned num_args, unsigned args[]) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_fixedpoint_add_fact(c, d, r, num_args, args);
|
||||
RESET_ERROR_CODE();
|
||||
to_fixedpoint_ref(d)->add_table_fact(to_func_decl(r), num_args, args);
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
Z3_lbool Z3_API Z3_fixedpoint_query(Z3_context c,Z3_fixedpoint d, Z3_ast q) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_fixedpoint_query(c, d, q);
|
||||
RESET_ERROR_CODE();
|
||||
lbool r = l_undef;
|
||||
cancel_eh<api::fixedpoint_context> eh(*to_fixedpoint_ref(d));
|
||||
unsigned timeout = to_fixedpoint(d)->m_params.get_uint(":timeout", UINT_MAX);
|
||||
api::context::set_interruptable(*(mk_c(c)), eh);
|
||||
{
|
||||
scoped_timer timer(timeout, &eh);
|
||||
try {
|
||||
r = to_fixedpoint_ref(d)->ctx().query(to_expr(q));
|
||||
}
|
||||
catch (z3_exception& ex) {
|
||||
mk_c(c)->handle_exception(ex);
|
||||
r = l_undef;
|
||||
}
|
||||
to_fixedpoint_ref(d)->ctx().cleanup();
|
||||
}
|
||||
return of_lbool(r);
|
||||
Z3_CATCH_RETURN(Z3_L_UNDEF);
|
||||
}
|
||||
|
||||
Z3_lbool Z3_API Z3_fixedpoint_query_relations(
|
||||
__in Z3_context c,__in Z3_fixedpoint d,
|
||||
__in unsigned num_relations, Z3_func_decl const relations[]) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_fixedpoint_query_relations(c, d, num_relations, relations);
|
||||
RESET_ERROR_CODE();
|
||||
lbool r = l_undef;
|
||||
unsigned timeout = to_fixedpoint(d)->m_params.get_uint(":timeout", UINT_MAX);
|
||||
cancel_eh<api::fixedpoint_context> eh(*to_fixedpoint_ref(d));
|
||||
api::context::set_interruptable(*(mk_c(c)), eh);
|
||||
{
|
||||
scoped_timer timer(timeout, &eh);
|
||||
try {
|
||||
r = to_fixedpoint_ref(d)->ctx().dl_query(num_relations, to_func_decls(relations));
|
||||
}
|
||||
catch (z3_exception& ex) {
|
||||
mk_c(c)->handle_exception(ex);
|
||||
r = l_undef;
|
||||
}
|
||||
to_fixedpoint_ref(d)->ctx().cleanup();
|
||||
}
|
||||
return of_lbool(r);
|
||||
Z3_CATCH_RETURN(Z3_L_UNDEF);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_fixedpoint_get_answer(Z3_context c, Z3_fixedpoint d) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_fixedpoint_get_answer(c, d);
|
||||
RESET_ERROR_CODE();
|
||||
expr* e = to_fixedpoint_ref(d)->ctx().get_answer_as_formula();
|
||||
mk_c(c)->save_ast_trail(e);
|
||||
RETURN_Z3(of_expr(e));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_string Z3_API Z3_fixedpoint_get_reason_unknown(Z3_context c,Z3_fixedpoint d) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_fixedpoint_get_reason_unknown(c, d);
|
||||
RESET_ERROR_CODE();
|
||||
return mk_c(c)->mk_external_string(to_fixedpoint_ref(d)->get_last_status());
|
||||
Z3_CATCH_RETURN("");
|
||||
}
|
||||
|
||||
Z3_string Z3_API Z3_fixedpoint_to_string(
|
||||
Z3_context c,
|
||||
Z3_fixedpoint d,
|
||||
unsigned num_queries,
|
||||
Z3_ast _queries[]) {
|
||||
Z3_TRY;
|
||||
expr*const* queries = to_exprs(_queries);
|
||||
LOG_Z3_fixedpoint_to_string(c, d, num_queries, _queries);
|
||||
RESET_ERROR_CODE();
|
||||
return mk_c(c)->mk_external_string(to_fixedpoint_ref(d)->to_string(num_queries, queries));
|
||||
Z3_CATCH_RETURN("");
|
||||
}
|
||||
|
||||
Z3_stats Z3_API Z3_fixedpoint_get_statistics(Z3_context c,Z3_fixedpoint d) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_fixedpoint_get_statistics(c, d);
|
||||
RESET_ERROR_CODE();
|
||||
Z3_stats_ref * st = alloc(Z3_stats_ref);
|
||||
to_fixedpoint_ref(d)->ctx().collect_statistics(st->m_stats);
|
||||
mk_c(c)->save_object(st);
|
||||
Z3_stats r = of_stats(st);
|
||||
RETURN_Z3(r);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
void Z3_API Z3_fixedpoint_register_relation(Z3_context c,Z3_fixedpoint d, Z3_func_decl f) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_fixedpoint_register_relation(c, d, f);
|
||||
to_fixedpoint_ref(d)->ctx().register_predicate(to_func_decl(f));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_fixedpoint_set_predicate_representation(
|
||||
Z3_context c,
|
||||
Z3_fixedpoint d,
|
||||
Z3_func_decl f,
|
||||
unsigned num_relations,
|
||||
Z3_symbol const relation_kinds[]) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_fixedpoint_set_predicate_representation(c, d, f, num_relations, relation_kinds);
|
||||
svector<symbol> kinds;
|
||||
for (unsigned i = 0; i < num_relations; ++i) {
|
||||
kinds.push_back(to_symbol(relation_kinds[i]));
|
||||
}
|
||||
to_fixedpoint_ref(d)->ctx().set_predicate_representation(to_func_decl(f), num_relations, kinds.c_ptr());
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_fixedpoint_set_reduce_assign_callback(
|
||||
Z3_context c, Z3_fixedpoint d, Z3_fixedpoint_reduce_assign_callback_fptr f) {
|
||||
Z3_TRY;
|
||||
// no logging
|
||||
to_fixedpoint_ref(d)->set_reduce_assign((reduce_assign_callback_fptr)f);
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_fixedpoint_set_reduce_app_callback(
|
||||
Z3_context c, Z3_fixedpoint d, Z3_fixedpoint_reduce_app_callback_fptr f) {
|
||||
Z3_TRY;
|
||||
// no logging
|
||||
to_fixedpoint_ref(d)->set_reduce_app((reduce_app_callback_fptr)f);
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
Z3_ast_vector Z3_API Z3_fixedpoint_simplify_rules(
|
||||
Z3_context c,
|
||||
Z3_fixedpoint d,
|
||||
unsigned num_rules,
|
||||
Z3_ast _rules[],
|
||||
unsigned num_outputs,
|
||||
Z3_func_decl _outputs[]) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_fixedpoint_simplify_rules(c, d, num_rules, _rules, num_outputs, _outputs);
|
||||
RESET_ERROR_CODE();
|
||||
expr** rules = (expr**)_rules;
|
||||
func_decl** outputs = (func_decl**)_outputs;
|
||||
ast_manager& m = mk_c(c)->m();
|
||||
expr_ref_vector result(m);
|
||||
to_fixedpoint_ref(d)->simplify_rules(num_rules, rules, num_outputs, outputs, result);
|
||||
Z3_ast_vector_ref* v = alloc(Z3_ast_vector_ref, mk_c(c)->m());
|
||||
mk_c(c)->save_object(v);
|
||||
for (unsigned i = 0; i < result.size(); ++i) {
|
||||
v->m_ast_vector.push_back(result[i].get());
|
||||
}
|
||||
RETURN_Z3(of_ast_vector(v));
|
||||
Z3_CATCH_RETURN(0)
|
||||
}
|
||||
|
||||
|
||||
void Z3_API Z3_fixedpoint_init(Z3_context c,Z3_fixedpoint d, void* state) {
|
||||
Z3_TRY;
|
||||
// not logged
|
||||
to_fixedpoint_ref(d)->set_state(state);
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
|
||||
void Z3_API Z3_fixedpoint_update_rule(Z3_context c, Z3_fixedpoint d, Z3_ast a, Z3_symbol name) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_fixedpoint_update_rule(c, d, a, name);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_FORMULA(a,);
|
||||
to_fixedpoint_ref(d)->update_rule(to_expr(a), to_symbol(name));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
unsigned Z3_API Z3_fixedpoint_get_num_levels(Z3_context c, Z3_fixedpoint d, Z3_func_decl pred) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_fixedpoint_get_num_levels(c, d, pred);
|
||||
RESET_ERROR_CODE();
|
||||
return to_fixedpoint_ref(d)->get_num_levels(to_func_decl(pred));
|
||||
Z3_CATCH_RETURN(0)
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_fixedpoint_get_cover_delta(Z3_context c, Z3_fixedpoint d, int level, Z3_func_decl pred) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_fixedpoint_get_cover_delta(c, d, level, pred);
|
||||
RESET_ERROR_CODE();
|
||||
expr_ref r = to_fixedpoint_ref(d)->get_cover_delta(level, to_func_decl(pred));
|
||||
mk_c(c)->save_ast_trail(r);
|
||||
RETURN_Z3(of_expr(r.get()));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
void Z3_API Z3_fixedpoint_add_cover(Z3_context c, Z3_fixedpoint d, int level, Z3_func_decl pred, Z3_ast property) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_fixedpoint_add_cover(c, d, level, pred, property);
|
||||
RESET_ERROR_CODE();
|
||||
to_fixedpoint_ref(d)->add_cover(level, to_func_decl(pred), to_expr(property));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
Z3_string Z3_API Z3_fixedpoint_get_help(Z3_context c, Z3_fixedpoint d) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_fixedpoint_get_help(c, d);
|
||||
RESET_ERROR_CODE();
|
||||
std::ostringstream buffer;
|
||||
param_descrs descrs;
|
||||
to_fixedpoint_ref(d)->collect_param_descrs(descrs);
|
||||
descrs.display(buffer);
|
||||
return mk_c(c)->mk_external_string(buffer.str());
|
||||
Z3_CATCH_RETURN("");
|
||||
}
|
||||
|
||||
Z3_param_descrs Z3_API Z3_fixedpoint_get_param_descrs(Z3_context c, Z3_fixedpoint f) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_fixedpoint_get_param_descrs(c, f);
|
||||
RESET_ERROR_CODE();
|
||||
Z3_param_descrs_ref * d = alloc(Z3_param_descrs_ref);
|
||||
mk_c(c)->save_object(d);
|
||||
to_fixedpoint_ref(f)->collect_param_descrs(d->m_descrs);
|
||||
Z3_param_descrs r = of_param_descrs(d);
|
||||
RETURN_Z3(r);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
void Z3_API Z3_fixedpoint_set_params(Z3_context c, Z3_fixedpoint d, Z3_params p) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_fixedpoint_set_params(c, d, p);
|
||||
RESET_ERROR_CODE();
|
||||
param_descrs descrs;
|
||||
to_fixedpoint_ref(d)->collect_param_descrs(descrs);
|
||||
to_params(p)->m_params.validate(descrs);
|
||||
to_fixedpoint_ref(d)->updt_params(to_param_ref(p));
|
||||
to_fixedpoint(d)->m_params = to_param_ref(p);
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_fixedpoint_push(Z3_context c,Z3_fixedpoint d) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_fixedpoint_push(c, d);
|
||||
RESET_ERROR_CODE();
|
||||
to_fixedpoint_ref(d)->ctx().push();
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_fixedpoint_pop(Z3_context c,Z3_fixedpoint d) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_fixedpoint_pop(c, d);
|
||||
RESET_ERROR_CODE();
|
||||
to_fixedpoint_ref(d)->ctx().pop();
|
||||
Z3_CATCH;
|
||||
|
||||
}
|
||||
|
||||
|
||||
};
|
84
src/api/api_datalog.h
Normal file
84
src/api/api_datalog.h
Normal file
|
@ -0,0 +1,84 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
api_datalog.h
|
||||
|
||||
Abstract:
|
||||
Datalog API
|
||||
old external_relation_context_impl
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2012-02-29.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _API_DATALOG_H_
|
||||
#define _API_DATALOG_H_
|
||||
|
||||
#include"z3.h"
|
||||
#include"ast.h"
|
||||
#include"front_end_params.h"
|
||||
#include"dl_external_relation.h"
|
||||
#include"dl_decl_plugin.h"
|
||||
#include"smt_solver.h"
|
||||
#include"api_util.h"
|
||||
#include"dl_context.h"
|
||||
|
||||
typedef void (*reduce_app_callback_fptr)(void*, func_decl*, unsigned, expr*const*, expr**);
|
||||
typedef void (*reduce_assign_callback_fptr)(void*, func_decl*, unsigned, expr*const*, unsigned, expr*const*);
|
||||
|
||||
namespace api {
|
||||
|
||||
class fixedpoint_context : public datalog::external_relation_context {
|
||||
void * m_state;
|
||||
reduce_app_callback_fptr m_reduce_app;
|
||||
reduce_assign_callback_fptr m_reduce_assign;
|
||||
datalog::context m_context;
|
||||
ast_ref_vector m_trail;
|
||||
public:
|
||||
fixedpoint_context(ast_manager& m, front_end_params& p);
|
||||
virtual ~fixedpoint_context() {}
|
||||
family_id get_family_id() const { return const_cast<datalog::context&>(m_context).get_decl_util().get_family_id(); }
|
||||
void set_state(void* state);
|
||||
void set_reduce_app(reduce_app_callback_fptr f) { m_reduce_app = f; }
|
||||
void set_reduce_assign(reduce_assign_callback_fptr f) { m_reduce_assign = f; }
|
||||
virtual void reduce(func_decl* f, unsigned num_args, expr * const* args, expr_ref& result);
|
||||
virtual void reduce_assign(func_decl* f, unsigned num_args, expr * const* args, unsigned num_out, expr* const* outs);
|
||||
datalog::context& ctx() { return m_context; }
|
||||
void add_rule(expr* rule, symbol const& name);
|
||||
void update_rule(expr* rule, symbol const& name);
|
||||
void add_table_fact(func_decl* r, unsigned num_args, unsigned args[]);
|
||||
std::string get_last_status();
|
||||
std::string to_string(unsigned num_queries, expr*const* queries);
|
||||
void cancel() { m_context.cancel(); }
|
||||
|
||||
unsigned get_num_levels(func_decl* pred);
|
||||
expr_ref get_cover_delta(int level, func_decl* pred);
|
||||
void add_cover(int level, func_decl* pred, expr* predicate);
|
||||
void collect_param_descrs(param_descrs & p) { m_context.collect_params(p); }
|
||||
void updt_params(params_ref const& p) { m_context.updt_params(p); }
|
||||
|
||||
void simplify_rules(
|
||||
unsigned num_rules, expr* const* rules,
|
||||
unsigned num_outputs, func_decl* const* outputs, expr_ref_vector& result);
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
struct Z3_fixedpoint_ref : public api::object {
|
||||
api::fixedpoint_context * m_datalog;
|
||||
params_ref m_params;
|
||||
Z3_fixedpoint_ref():m_datalog(0) {}
|
||||
virtual ~Z3_fixedpoint_ref() { dealloc(m_datalog); }
|
||||
};
|
||||
|
||||
inline Z3_fixedpoint_ref * to_fixedpoint(Z3_fixedpoint s) { return reinterpret_cast<Z3_fixedpoint_ref *>(s); }
|
||||
inline Z3_fixedpoint of_datalog(Z3_fixedpoint_ref * s) { return reinterpret_cast<Z3_fixedpoint>(s); }
|
||||
inline api::fixedpoint_context * to_fixedpoint_ref(Z3_fixedpoint s) { return to_fixedpoint(s)->m_datalog; }
|
||||
|
||||
|
||||
#endif
|
621
src/api/api_datatype.cpp
Normal file
621
src/api/api_datatype.cpp
Normal file
|
@ -0,0 +1,621 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
api_datatype.cpp
|
||||
|
||||
Abstract:
|
||||
API for datatype theory
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2012-02-29.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include<iostream>
|
||||
#include"z3.h"
|
||||
#include"api_log_macros.h"
|
||||
#include"api_context.h"
|
||||
#include"api_util.h"
|
||||
#include"datatype_decl_plugin.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
Z3_sort Z3_API Z3_mk_tuple_sort(Z3_context c,
|
||||
Z3_symbol name,
|
||||
unsigned num_fields,
|
||||
Z3_symbol const field_names[],
|
||||
Z3_sort const field_sorts[],
|
||||
Z3_func_decl * mk_tuple_decl,
|
||||
Z3_func_decl proj_decls[]) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_tuple_sort(c, name, num_fields, field_names, field_sorts, mk_tuple_decl, proj_decls);
|
||||
RESET_ERROR_CODE();
|
||||
mk_c(c)->reset_last_result();
|
||||
ast_manager& m = mk_c(c)->m();
|
||||
datatype_util dt_util(m);
|
||||
|
||||
sort_ref_vector tuples(m);
|
||||
sort* tuple;
|
||||
std::string recognizer_s("is_");
|
||||
recognizer_s += to_symbol(name).str();
|
||||
symbol recognizer(recognizer_s.c_str());
|
||||
|
||||
ptr_vector<accessor_decl> acc;
|
||||
for (unsigned i = 0; i < num_fields; ++i) {
|
||||
acc.push_back(mk_accessor_decl(to_symbol(field_names[i]), type_ref(to_sort(field_sorts[i]))));
|
||||
}
|
||||
|
||||
constructor_decl* constrs[1] = { mk_constructor_decl(to_symbol(name), recognizer, acc.size(), acc.c_ptr()) };
|
||||
|
||||
{
|
||||
datatype_decl * dt = mk_datatype_decl(to_symbol(name), 1, constrs);
|
||||
bool is_ok = mk_c(c)->get_dt_plugin()->mk_datatypes(1, &dt, tuples);
|
||||
del_datatype_decl(dt);
|
||||
|
||||
if (!is_ok) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
}
|
||||
|
||||
// create tuple type
|
||||
SASSERT(tuples.size() == 1);
|
||||
tuple = tuples[0].get();
|
||||
mk_c(c)->save_multiple_ast_trail(tuple);
|
||||
|
||||
// create constructor
|
||||
SASSERT(dt_util.is_datatype(tuple));
|
||||
SASSERT(!dt_util.is_recursive(tuple));
|
||||
ptr_vector<func_decl> const * decls = dt_util.get_datatype_constructors(tuple);
|
||||
func_decl* decl = (*decls)[0];
|
||||
mk_c(c)->save_multiple_ast_trail(decl);
|
||||
*mk_tuple_decl = of_func_decl(decl);
|
||||
|
||||
// Create projections
|
||||
ptr_vector<func_decl> const * accs = dt_util.get_constructor_accessors(decl);
|
||||
if (!accs) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
ptr_vector<func_decl> const & _accs = *accs;
|
||||
SASSERT(_accs.size() == num_fields);
|
||||
for (unsigned i = 0; i < _accs.size(); i++) {
|
||||
mk_c(c)->save_multiple_ast_trail(_accs[i]);
|
||||
proj_decls[i] = of_func_decl(_accs[i]);
|
||||
}
|
||||
RETURN_Z3_mk_tuple_sort(of_sort(tuple));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_sort Z3_API Z3_mk_enumeration_sort(Z3_context c,
|
||||
Z3_symbol name,
|
||||
unsigned n,
|
||||
Z3_symbol const enum_names[],
|
||||
Z3_func_decl enum_consts[],
|
||||
Z3_func_decl enum_testers[]) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_enumeration_sort(c, name, n, enum_names, enum_consts, enum_testers);
|
||||
RESET_ERROR_CODE();
|
||||
mk_c(c)->reset_last_result();
|
||||
ast_manager& m = mk_c(c)->m();
|
||||
datatype_util dt_util(m);
|
||||
|
||||
sort_ref_vector sorts(m);
|
||||
sort* e;
|
||||
|
||||
ptr_vector<constructor_decl> constrs;
|
||||
for (unsigned i = 0; i < n; ++i) {
|
||||
symbol e_name(to_symbol(enum_names[i]));
|
||||
std::string recognizer_s("is_");
|
||||
recognizer_s += e_name.str();
|
||||
symbol recognizer(recognizer_s.c_str());
|
||||
|
||||
constrs.push_back(mk_constructor_decl(e_name, recognizer, 0, 0));
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
datatype_decl * dt = mk_datatype_decl(to_symbol(name), n, constrs.c_ptr());
|
||||
bool is_ok = mk_c(c)->get_dt_plugin()->mk_datatypes(1, &dt, sorts);
|
||||
del_datatype_decl(dt);
|
||||
|
||||
if (!is_ok) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
}
|
||||
|
||||
// create enum type.
|
||||
SASSERT(sorts.size() == 1);
|
||||
e = sorts[0].get();
|
||||
mk_c(c)->save_multiple_ast_trail(e);
|
||||
|
||||
// create constructor
|
||||
SASSERT(dt_util.is_datatype(e));
|
||||
SASSERT(!dt_util.is_recursive(e));
|
||||
ptr_vector<func_decl> const * decls = dt_util.get_datatype_constructors(e);
|
||||
SASSERT(decls && decls->size() == n);
|
||||
for (unsigned i = 0; i < n; ++i) {
|
||||
func_decl* decl = (*decls)[i];
|
||||
mk_c(c)->save_multiple_ast_trail(decl);
|
||||
enum_consts[i] = of_func_decl(decl);
|
||||
decl = dt_util.get_constructor_recognizer(decl);
|
||||
mk_c(c)->save_multiple_ast_trail(decl);
|
||||
enum_testers[i] = of_func_decl(decl);
|
||||
}
|
||||
|
||||
RETURN_Z3_mk_enumeration_sort(of_sort(e));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_sort Z3_API Z3_mk_list_sort(Z3_context c,
|
||||
Z3_symbol name,
|
||||
Z3_sort elem_sort,
|
||||
Z3_func_decl* nil_decl,
|
||||
Z3_func_decl* is_nil_decl,
|
||||
Z3_func_decl* cons_decl,
|
||||
Z3_func_decl* is_cons_decl,
|
||||
Z3_func_decl* head_decl,
|
||||
Z3_func_decl* tail_decl
|
||||
) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_list_sort(c, name, elem_sort, nil_decl, is_nil_decl, cons_decl, is_cons_decl, head_decl, tail_decl);
|
||||
RESET_ERROR_CODE();
|
||||
ast_manager& m = mk_c(c)->m();
|
||||
mk_c(c)->reset_last_result();
|
||||
datatype_util data_util(m);
|
||||
accessor_decl* head_tail[2] = {
|
||||
mk_accessor_decl(symbol("head"), type_ref(to_sort(elem_sort))),
|
||||
mk_accessor_decl(symbol("tail"), type_ref(0))
|
||||
};
|
||||
constructor_decl* constrs[2] = {
|
||||
mk_constructor_decl(symbol("nil"), symbol("is_nil"), 0, 0),
|
||||
// Leo: SMT 2.0 document uses 'insert' instead of cons
|
||||
mk_constructor_decl(symbol("cons"), symbol("is_cons"), 2, head_tail)
|
||||
};
|
||||
|
||||
sort_ref_vector sorts(m);
|
||||
{
|
||||
datatype_decl * decl = mk_datatype_decl(to_symbol(name), 2, constrs);
|
||||
bool is_ok = mk_c(c)->get_dt_plugin()->mk_datatypes(1, &decl, sorts);
|
||||
del_datatype_decl(decl);
|
||||
|
||||
if (!is_ok) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
}
|
||||
sort * s = sorts.get(0);
|
||||
|
||||
mk_c(c)->save_multiple_ast_trail(s);
|
||||
ptr_vector<func_decl> const& cnstrs = *data_util.get_datatype_constructors(s);
|
||||
SASSERT(cnstrs.size() == 2);
|
||||
func_decl* f;
|
||||
if (nil_decl) {
|
||||
f = cnstrs[0];
|
||||
mk_c(c)->save_multiple_ast_trail(f);
|
||||
*nil_decl = of_func_decl(f);
|
||||
}
|
||||
if (is_nil_decl) {
|
||||
f = data_util.get_constructor_recognizer(cnstrs[0]);
|
||||
mk_c(c)->save_multiple_ast_trail(f);
|
||||
*is_nil_decl = of_func_decl(f);
|
||||
}
|
||||
if (cons_decl) {
|
||||
f = cnstrs[1];
|
||||
mk_c(c)->save_multiple_ast_trail(f);
|
||||
*cons_decl = of_func_decl(f);
|
||||
}
|
||||
if (is_cons_decl) {
|
||||
f = data_util.get_constructor_recognizer(cnstrs[1]);
|
||||
mk_c(c)->save_multiple_ast_trail(f);
|
||||
*is_cons_decl = of_func_decl(f);
|
||||
}
|
||||
if (head_decl) {
|
||||
ptr_vector<func_decl> const* acc = data_util.get_constructor_accessors(cnstrs[1]);
|
||||
SASSERT(acc);
|
||||
SASSERT(acc->size() == 2);
|
||||
f = (*acc)[0];
|
||||
mk_c(c)->save_multiple_ast_trail(f);
|
||||
*head_decl = of_func_decl(f);
|
||||
}
|
||||
if (tail_decl) {
|
||||
ptr_vector<func_decl> const* acc = data_util.get_constructor_accessors(cnstrs[1]);
|
||||
SASSERT(acc);
|
||||
SASSERT(acc->size() == 2);
|
||||
f = (*acc)[1];
|
||||
mk_c(c)->save_multiple_ast_trail(f);
|
||||
*tail_decl = of_func_decl(f);
|
||||
}
|
||||
RETURN_Z3_mk_list_sort(of_sort(s));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
struct constructor {
|
||||
symbol m_name;
|
||||
symbol m_tester;
|
||||
svector<symbol> m_field_names;
|
||||
sort_ref_vector m_sorts;
|
||||
unsigned_vector m_sort_refs;
|
||||
func_decl_ref m_constructor;
|
||||
constructor(ast_manager& m) : m_sorts(m), m_constructor(m) {}
|
||||
};
|
||||
|
||||
Z3_constructor Z3_API Z3_mk_constructor(Z3_context c,
|
||||
Z3_symbol name,
|
||||
Z3_symbol tester,
|
||||
unsigned num_fields,
|
||||
Z3_symbol const field_names[],
|
||||
Z3_sort const sorts[],
|
||||
unsigned sort_refs[]
|
||||
) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_constructor(c, name, tester, num_fields, field_names, sorts, sort_refs);
|
||||
RESET_ERROR_CODE();
|
||||
ast_manager& m = mk_c(c)->m();
|
||||
constructor* cnstr = alloc(constructor, m);
|
||||
cnstr->m_name = to_symbol(name);
|
||||
cnstr->m_tester = to_symbol(tester);
|
||||
for (unsigned i = 0; i < num_fields; ++i) {
|
||||
cnstr->m_field_names.push_back(to_symbol(field_names[i]));
|
||||
cnstr->m_sorts.push_back(to_sort(sorts[i]));
|
||||
cnstr->m_sort_refs.push_back(sort_refs[i]);
|
||||
}
|
||||
RETURN_Z3(reinterpret_cast<Z3_constructor>(cnstr));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
|
||||
void Z3_API Z3_query_constructor(Z3_context c,
|
||||
Z3_constructor constr,
|
||||
unsigned num_fields,
|
||||
Z3_func_decl* constructor_decl,
|
||||
Z3_func_decl* tester,
|
||||
Z3_func_decl accessors[]) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_query_constructor(c, constr, num_fields, constructor_decl, tester, accessors);
|
||||
RESET_ERROR_CODE();
|
||||
mk_c(c)->reset_last_result();
|
||||
if (!constr) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
return;
|
||||
}
|
||||
ast_manager& m = mk_c(c)->m();
|
||||
datatype_util data_util(m);
|
||||
func_decl* f = reinterpret_cast<constructor*>(constr)->m_constructor.get();
|
||||
|
||||
if (!f) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
return;
|
||||
}
|
||||
if (constructor_decl) {
|
||||
mk_c(c)->save_multiple_ast_trail(f);
|
||||
*constructor_decl = of_func_decl(f);
|
||||
}
|
||||
if (tester) {
|
||||
func_decl* f2 = data_util.get_constructor_recognizer(f);
|
||||
mk_c(c)->save_multiple_ast_trail(f2);
|
||||
*tester = of_func_decl(f2);
|
||||
}
|
||||
|
||||
ptr_vector<func_decl> const* accs = data_util.get_constructor_accessors(f);
|
||||
if (!accs && num_fields > 0) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
return;
|
||||
}
|
||||
for (unsigned i = 0; i < num_fields; ++i) {
|
||||
func_decl* f2 = (*accs)[i];
|
||||
mk_c(c)->save_multiple_ast_trail(f2);
|
||||
accessors[i] = of_func_decl(f2);
|
||||
}
|
||||
RETURN_Z3_query_constructor;
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_del_constructor(Z3_context c, Z3_constructor constr) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_del_constructor(c, constr);
|
||||
RESET_ERROR_CODE();
|
||||
dealloc(reinterpret_cast<constructor*>(constr));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
static datatype_decl* mk_datatype_decl(Z3_context c,
|
||||
Z3_symbol name,
|
||||
unsigned num_constructors,
|
||||
Z3_constructor constructors[]) {
|
||||
ptr_vector<constructor_decl> constrs;
|
||||
for (unsigned i = 0; i < num_constructors; ++i) {
|
||||
constructor* cn = reinterpret_cast<constructor*>(constructors[i]);
|
||||
ptr_vector<accessor_decl> acc;
|
||||
for (unsigned j = 0; j < cn->m_sorts.size(); ++j) {
|
||||
if (cn->m_sorts[j].get()) {
|
||||
acc.push_back(mk_accessor_decl(cn->m_field_names[j], type_ref(cn->m_sorts[j].get())));
|
||||
}
|
||||
else {
|
||||
acc.push_back(mk_accessor_decl(cn->m_field_names[j], type_ref(cn->m_sort_refs[j])));
|
||||
}
|
||||
}
|
||||
constrs.push_back(mk_constructor_decl(cn->m_name, cn->m_tester, acc.size(), acc.c_ptr()));
|
||||
}
|
||||
return mk_datatype_decl(to_symbol(name), num_constructors, constrs.c_ptr());
|
||||
}
|
||||
|
||||
Z3_sort Z3_API Z3_mk_datatype(Z3_context c,
|
||||
Z3_symbol name,
|
||||
unsigned num_constructors,
|
||||
Z3_constructor constructors[]) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_datatype(c, name, num_constructors, constructors);
|
||||
RESET_ERROR_CODE();
|
||||
ast_manager& m = mk_c(c)->m();
|
||||
datatype_util data_util(m);
|
||||
|
||||
sort_ref_vector sorts(m);
|
||||
{
|
||||
datatype_decl * data = mk_datatype_decl(c, name, num_constructors, constructors);
|
||||
bool is_ok = mk_c(c)->get_dt_plugin()->mk_datatypes(1, &data, sorts);
|
||||
del_datatype_decl(data);
|
||||
|
||||
if (!is_ok) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
}
|
||||
sort * s = sorts.get(0);
|
||||
|
||||
mk_c(c)->save_ast_trail(s);
|
||||
ptr_vector<func_decl> const* cnstrs = data_util.get_datatype_constructors(s);
|
||||
|
||||
for (unsigned i = 0; i < num_constructors; ++i) {
|
||||
constructor* cn = reinterpret_cast<constructor*>(constructors[i]);
|
||||
cn->m_constructor = (*cnstrs)[i];
|
||||
}
|
||||
RETURN_Z3_mk_datatype(of_sort(s));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
typedef ptr_vector<constructor> constructor_list;
|
||||
|
||||
Z3_constructor_list Z3_API Z3_mk_constructor_list(Z3_context c,
|
||||
unsigned num_constructors,
|
||||
Z3_constructor const constructors[]) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_constructor_list(c, num_constructors, constructors);
|
||||
RESET_ERROR_CODE();
|
||||
constructor_list* result = alloc(ptr_vector<constructor>);
|
||||
for (unsigned i = 0; i < num_constructors; ++i) {
|
||||
result->push_back(reinterpret_cast<constructor*>(constructors[i]));
|
||||
}
|
||||
RETURN_Z3(reinterpret_cast<Z3_constructor_list>(result));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
void Z3_API Z3_del_constructor_list(Z3_context c, Z3_constructor_list clist) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_del_constructor_list(c, clist);
|
||||
RESET_ERROR_CODE();
|
||||
dealloc(reinterpret_cast<constructor_list*>(clist));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_mk_datatypes(Z3_context c,
|
||||
unsigned num_sorts,
|
||||
Z3_symbol const sort_names[],
|
||||
Z3_sort sorts[],
|
||||
Z3_constructor_list constructor_lists[]) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_datatypes(c, num_sorts, sort_names, sorts, constructor_lists);
|
||||
RESET_ERROR_CODE();
|
||||
ast_manager& m = mk_c(c)->m();
|
||||
mk_c(c)->reset_last_result();
|
||||
datatype_util data_util(m);
|
||||
|
||||
ptr_vector<datatype_decl> datas;
|
||||
for (unsigned i = 0; i < num_sorts; ++i) {
|
||||
constructor_list* cl = reinterpret_cast<constructor_list*>(constructor_lists[i]);
|
||||
datas.push_back(mk_datatype_decl(c,sort_names[i], cl->size(), reinterpret_cast<Z3_constructor*>(cl->c_ptr())));
|
||||
}
|
||||
sort_ref_vector _sorts(m);
|
||||
bool ok = mk_c(c)->get_dt_plugin()->mk_datatypes(datas.size(), datas.c_ptr(), _sorts);
|
||||
del_datatype_decls(datas.size(), datas.c_ptr());
|
||||
|
||||
if (!ok) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
return;
|
||||
}
|
||||
|
||||
SASSERT(_sorts.size() == num_sorts);
|
||||
for (unsigned i = 0; i < _sorts.size(); ++i) {
|
||||
sort* s = _sorts[i].get();
|
||||
mk_c(c)->save_multiple_ast_trail(s);
|
||||
sorts[i] = of_sort(s);
|
||||
constructor_list* cl = reinterpret_cast<constructor_list*>(constructor_lists[i]);
|
||||
ptr_vector<func_decl> const* cnstrs = data_util.get_datatype_constructors(s);
|
||||
for (unsigned j = 0; j < cl->size(); ++j) {
|
||||
constructor* cn = (*cl)[j];
|
||||
cn->m_constructor = (*cnstrs)[j];
|
||||
}
|
||||
}
|
||||
RETURN_Z3_mk_datatypes;
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
unsigned Z3_API Z3_get_datatype_sort_num_constructors(Z3_context c, Z3_sort t) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_datatype_sort_num_constructors(c, t);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_VALID_AST(t, 0);
|
||||
sort * _t = to_sort(t);
|
||||
datatype_util dt_util(mk_c(c)->m());
|
||||
|
||||
if (!dt_util.is_datatype(_t)) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
return 0;
|
||||
}
|
||||
ptr_vector<func_decl> const * decls = dt_util.get_datatype_constructors(_t);
|
||||
if (!decls) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
return 0;
|
||||
}
|
||||
return decls->size();
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_func_decl get_datatype_sort_constructor_core(Z3_context c, Z3_sort t, unsigned idx) {
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_VALID_AST(t, 0);
|
||||
sort * _t = to_sort(t);
|
||||
datatype_util dt_util(mk_c(c)->m());
|
||||
if (!dt_util.is_datatype(_t)) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
return 0;
|
||||
}
|
||||
ptr_vector<func_decl> const * decls = dt_util.get_datatype_constructors(_t);
|
||||
if (!decls || idx >= decls->size()) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
return 0;
|
||||
}
|
||||
func_decl* decl = (*decls)[idx];
|
||||
mk_c(c)->save_ast_trail(decl);
|
||||
return of_func_decl(decl);
|
||||
}
|
||||
|
||||
Z3_func_decl Z3_API Z3_get_datatype_sort_constructor(Z3_context c, Z3_sort t, unsigned idx) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_datatype_sort_constructor(c, t, idx);
|
||||
RESET_ERROR_CODE();
|
||||
Z3_func_decl r = get_datatype_sort_constructor_core(c, t, idx);
|
||||
RETURN_Z3(r);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_func_decl Z3_API Z3_get_datatype_sort_recognizer(Z3_context c, Z3_sort t, unsigned idx) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_datatype_sort_recognizer(c, t, idx);
|
||||
RESET_ERROR_CODE();
|
||||
sort * _t = to_sort(t);
|
||||
datatype_util dt_util(mk_c(c)->m());
|
||||
|
||||
if (!dt_util.is_datatype(_t)) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
ptr_vector<func_decl> const * decls = dt_util.get_datatype_constructors(_t);
|
||||
if (!decls || idx >= decls->size()) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
func_decl* decl = (*decls)[idx];
|
||||
decl = dt_util.get_constructor_recognizer(decl);
|
||||
mk_c(c)->save_ast_trail(decl);
|
||||
RETURN_Z3(of_func_decl(decl));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_func_decl Z3_API Z3_get_datatype_sort_constructor_accessor(Z3_context c, Z3_sort t, unsigned idx_c, unsigned idx_a) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_datatype_sort_constructor_accessor(c, t, idx_c, idx_a);
|
||||
RESET_ERROR_CODE();
|
||||
sort * _t = to_sort(t);
|
||||
datatype_util dt_util(mk_c(c)->m());
|
||||
|
||||
if (!dt_util.is_datatype(_t)) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
ptr_vector<func_decl> const * decls = dt_util.get_datatype_constructors(_t);
|
||||
if (!decls || idx_c >= decls->size()) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
func_decl* decl = (*decls)[idx_c];
|
||||
if (decl->get_arity() <= idx_a) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
ptr_vector<func_decl> const * accs = dt_util.get_constructor_accessors(decl);
|
||||
SASSERT(accs && accs->size() == decl->get_arity());
|
||||
if (!accs || accs->size() <= idx_a) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
decl = (*accs)[idx_a];
|
||||
mk_c(c)->save_ast_trail(decl);
|
||||
RETURN_Z3(of_func_decl(decl));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_func_decl Z3_API Z3_get_tuple_sort_mk_decl(Z3_context c, Z3_sort t) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_tuple_sort_mk_decl(c, t);
|
||||
RESET_ERROR_CODE();
|
||||
sort * tuple = to_sort(t);
|
||||
datatype_util dt_util(mk_c(c)->m());
|
||||
if (!dt_util.is_datatype(tuple) || dt_util.is_recursive(tuple) || dt_util.get_datatype_num_constructors(tuple) != 1) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
Z3_func_decl r = get_datatype_sort_constructor_core(c, t, 0);
|
||||
RETURN_Z3(r);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
unsigned Z3_API Z3_get_tuple_sort_num_fields(Z3_context c, Z3_sort t) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_tuple_sort_num_fields(c, t);
|
||||
RESET_ERROR_CODE();
|
||||
sort * tuple = to_sort(t);
|
||||
datatype_util dt_util(mk_c(c)->m());
|
||||
if (!dt_util.is_datatype(tuple) || dt_util.is_recursive(tuple) || dt_util.get_datatype_num_constructors(tuple) != 1) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
return 0;
|
||||
}
|
||||
ptr_vector<func_decl> const * decls = dt_util.get_datatype_constructors(tuple);
|
||||
if (!decls || decls->size() != 1) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
return 0;
|
||||
}
|
||||
ptr_vector<func_decl> const * accs = dt_util.get_constructor_accessors((*decls)[0]);
|
||||
if (!accs) {
|
||||
return 0;
|
||||
}
|
||||
return accs->size();
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_func_decl Z3_API Z3_get_tuple_sort_field_decl(Z3_context c, Z3_sort t, unsigned i) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_tuple_sort_field_decl(c, t, i);
|
||||
RESET_ERROR_CODE();
|
||||
sort * tuple = to_sort(t);
|
||||
datatype_util dt_util(mk_c(c)->m());
|
||||
if (!dt_util.is_datatype(tuple) || dt_util.is_recursive(tuple) || dt_util.get_datatype_num_constructors(tuple) != 1) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
ptr_vector<func_decl> const * decls = dt_util.get_datatype_constructors(tuple);
|
||||
if (!decls || decls->size() != 1) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
ptr_vector<func_decl> const * accs = dt_util.get_constructor_accessors((*decls)[0]);
|
||||
if (!accs) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
if (accs->size() <= i) {
|
||||
SET_ERROR_CODE(Z3_IOB);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
func_decl* acc = (*accs)[i];
|
||||
mk_c(c)->save_ast_trail(acc);
|
||||
RETURN_Z3(of_func_decl(acc));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
};
|
181
src/api/api_goal.cpp
Normal file
181
src/api/api_goal.cpp
Normal file
|
@ -0,0 +1,181 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
api_goal.cpp
|
||||
|
||||
Abstract:
|
||||
API for creating goals
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2012-03-06.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include<iostream>
|
||||
#include"z3.h"
|
||||
#include"api_log_macros.h"
|
||||
#include"api_context.h"
|
||||
#include"api_goal.h"
|
||||
#include"ast_translation.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
Z3_goal Z3_API Z3_mk_goal(Z3_context c, Z3_bool models, Z3_bool unsat_cores, Z3_bool proofs) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_goal(c, models, unsat_cores, proofs);
|
||||
RESET_ERROR_CODE();
|
||||
if (proofs != 0 && !mk_c(c)->m().proofs_enabled()) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
Z3_goal_ref * g = alloc(Z3_goal_ref);
|
||||
g->m_goal = alloc(goal, mk_c(c)->m(), proofs != 0, models != 0, unsat_cores != 0);
|
||||
mk_c(c)->save_object(g);
|
||||
Z3_goal r = of_goal(g);
|
||||
RETURN_Z3(r);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
void Z3_API Z3_goal_inc_ref(Z3_context c, Z3_goal g) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_goal_inc_ref(c, g);
|
||||
RESET_ERROR_CODE();
|
||||
to_goal(g)->inc_ref();
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_goal_dec_ref(Z3_context c, Z3_goal g) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_goal_dec_ref(c, g);
|
||||
RESET_ERROR_CODE();
|
||||
to_goal(g)->dec_ref();
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
Z3_goal_prec Z3_API Z3_goal_precision(Z3_context c, Z3_goal g) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_goal_precision(c, g);
|
||||
RESET_ERROR_CODE();
|
||||
switch (to_goal_ref(g)->prec()) {
|
||||
case goal::PRECISE: return Z3_GOAL_PRECISE;
|
||||
case goal::UNDER: return Z3_GOAL_UNDER;
|
||||
case goal::OVER: return Z3_GOAL_OVER;
|
||||
case goal::UNDER_OVER: return Z3_GOAL_UNDER_OVER;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return Z3_GOAL_UNDER_OVER;
|
||||
}
|
||||
Z3_CATCH_RETURN(Z3_GOAL_UNDER_OVER);
|
||||
}
|
||||
|
||||
void Z3_API Z3_goal_assert(Z3_context c, Z3_goal g, Z3_ast a) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_goal_assert(c, g, a);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_FORMULA(a,);
|
||||
to_goal_ref(g)->assert_expr(to_expr(a));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
Z3_bool Z3_API Z3_goal_inconsistent(Z3_context c, Z3_goal g) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_goal_inconsistent(c, g);
|
||||
RESET_ERROR_CODE();
|
||||
return to_goal_ref(g)->inconsistent();
|
||||
Z3_CATCH_RETURN(Z3_FALSE);
|
||||
}
|
||||
|
||||
unsigned Z3_API Z3_goal_depth(Z3_context c, Z3_goal g) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_goal_depth(c, g);
|
||||
RESET_ERROR_CODE();
|
||||
return to_goal_ref(g)->depth();
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
void Z3_API Z3_goal_reset(Z3_context c, Z3_goal g) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_goal_reset(c, g);
|
||||
RESET_ERROR_CODE();
|
||||
to_goal_ref(g)->reset();
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
unsigned Z3_API Z3_goal_size(Z3_context c, Z3_goal g) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_goal_size(c, g);
|
||||
RESET_ERROR_CODE();
|
||||
return to_goal_ref(g)->size();
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_goal_formula(Z3_context c, Z3_goal g, unsigned idx) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_goal_formula(c, g, idx);
|
||||
RESET_ERROR_CODE();
|
||||
if (idx >= to_goal_ref(g)->size()) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
expr * result = to_goal_ref(g)->form(idx);
|
||||
mk_c(c)->save_ast_trail(result);
|
||||
RETURN_Z3(of_ast(result));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
unsigned Z3_API Z3_goal_num_exprs(Z3_context c, Z3_goal g) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_goal_num_exprs(c, g);
|
||||
RESET_ERROR_CODE();
|
||||
return to_goal_ref(g)->num_exprs();
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_bool Z3_API Z3_goal_is_decided_sat(Z3_context c, Z3_goal g) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_goal_is_decided_sat(c, g);
|
||||
RESET_ERROR_CODE();
|
||||
return to_goal_ref(g)->is_decided_sat();
|
||||
Z3_CATCH_RETURN(Z3_FALSE);
|
||||
}
|
||||
|
||||
Z3_bool Z3_API Z3_goal_is_decided_unsat(Z3_context c, Z3_goal g) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_goal_is_decided_unsat(c, g);
|
||||
RESET_ERROR_CODE();
|
||||
return to_goal_ref(g)->is_decided_unsat();
|
||||
Z3_CATCH_RETURN(Z3_FALSE);
|
||||
}
|
||||
|
||||
Z3_goal Z3_API Z3_goal_translate(Z3_context c, Z3_goal g, Z3_context target) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_goal_translate(c, g, target);
|
||||
RESET_ERROR_CODE();
|
||||
ast_translation translator(mk_c(c)->m(), mk_c(target)->m());
|
||||
Z3_goal_ref * _r = alloc(Z3_goal_ref);
|
||||
_r->m_goal = to_goal_ref(g)->translate(translator);
|
||||
mk_c(target)->save_object(_r);
|
||||
Z3_goal r = of_goal(_r);
|
||||
RETURN_Z3(r);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_string Z3_API Z3_goal_to_string(Z3_context c, Z3_goal g) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_goal_to_string(c, g);
|
||||
RESET_ERROR_CODE();
|
||||
std::ostringstream buffer;
|
||||
to_goal_ref(g)->display(buffer);
|
||||
// Hack for removing the trailing '\n'
|
||||
std::string result = buffer.str();
|
||||
SASSERT(result.size() > 0);
|
||||
result.resize(result.size()-1);
|
||||
return mk_c(c)->mk_external_string(result);
|
||||
Z3_CATCH_RETURN("");
|
||||
}
|
||||
|
||||
};
|
33
src/api/api_goal.h
Normal file
33
src/api/api_goal.h
Normal file
|
@ -0,0 +1,33 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
api_goal.h
|
||||
|
||||
Abstract:
|
||||
API for creating goals
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2012-03-06.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _API_GOAL_H_
|
||||
#define _API_GOAL_H_
|
||||
|
||||
#include"api_util.h"
|
||||
#include"goal.h"
|
||||
|
||||
struct Z3_goal_ref : public api::object {
|
||||
goal_ref m_goal;
|
||||
virtual ~Z3_goal_ref() {}
|
||||
};
|
||||
|
||||
inline Z3_goal_ref * to_goal(Z3_goal g) { return reinterpret_cast<Z3_goal_ref *>(g); }
|
||||
inline Z3_goal of_goal(Z3_goal_ref * g) { return reinterpret_cast<Z3_goal>(g); }
|
||||
inline goal_ref to_goal_ref(Z3_goal g) { return g == 0 ? goal_ref() : to_goal(g)->m_goal; }
|
||||
|
||||
#endif
|
54
src/api/api_log.cpp
Normal file
54
src/api/api_log.cpp
Normal file
|
@ -0,0 +1,54 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
api_log.cpp
|
||||
|
||||
Abstract:
|
||||
API for creating logs
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2012-02-29.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include<iostream>
|
||||
#include<fstream>
|
||||
#include"z3.h"
|
||||
#include"api_log_macros.h"
|
||||
#include"util.h"
|
||||
|
||||
std::ostream * g_z3_log = 0;
|
||||
bool g_z3_log_enabled = false;
|
||||
|
||||
extern "C" {
|
||||
Z3_bool Z3_API Z3_open_log(Z3_string filename) {
|
||||
if (g_z3_log != 0)
|
||||
Z3_close_log();
|
||||
g_z3_log = alloc(std::ofstream, filename);
|
||||
g_z3_log_enabled = true;
|
||||
if (g_z3_log->bad() || g_z3_log->fail()) {
|
||||
dealloc(g_z3_log);
|
||||
g_z3_log = 0;
|
||||
return Z3_FALSE;
|
||||
}
|
||||
return Z3_TRUE;
|
||||
}
|
||||
|
||||
void Z3_API Z3_append_log(Z3_string str) {
|
||||
if (g_z3_log == 0)
|
||||
return;
|
||||
_Z3_append_log(static_cast<char const *>(str));
|
||||
}
|
||||
|
||||
void Z3_API Z3_close_log() {
|
||||
if (g_z3_log != 0) {
|
||||
dealloc(g_z3_log);
|
||||
g_z3_log_enabled = false;
|
||||
g_z3_log = 0;
|
||||
}
|
||||
}
|
||||
}
|
3355
src/api/api_log_macros.cpp
Normal file
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
989
src/api/api_log_macros.h
Normal 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
670
src/api/api_model.cpp
Normal file
|
@ -0,0 +1,670 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
api_quant.cpp
|
||||
|
||||
Abstract:
|
||||
API for models
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2012-02-29.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include<iostream>
|
||||
#include"z3.h"
|
||||
#include"api_log_macros.h"
|
||||
#include"api_context.h"
|
||||
#include"api_model.h"
|
||||
#include"api_ast_vector.h"
|
||||
#include"array_decl_plugin.h"
|
||||
#include"model.h"
|
||||
#include"model_v2_pp.h"
|
||||
#include"model_smt2_pp.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
void Z3_API Z3_model_inc_ref(Z3_context c, Z3_model m) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_model_inc_ref(c, m);
|
||||
RESET_ERROR_CODE();
|
||||
if (m) {
|
||||
to_model(m)->inc_ref();
|
||||
}
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_model_dec_ref(Z3_context c, Z3_model m) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_model_dec_ref(c, m);
|
||||
RESET_ERROR_CODE();
|
||||
if (m) {
|
||||
to_model(m)->dec_ref();
|
||||
}
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_model_get_const_interp(Z3_context c, Z3_model m, Z3_func_decl a) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_model_get_const_interp(c, m, a);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_NON_NULL(m, 0);
|
||||
expr * r = to_model_ref(m)->get_const_interp(to_func_decl(a));
|
||||
if (!r) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
RETURN_Z3(of_expr(r));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_func_interp Z3_API Z3_model_get_func_interp(Z3_context c, Z3_model m, Z3_func_decl f) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_model_get_func_interp(c, m, f);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_NON_NULL(m, 0);
|
||||
func_interp * _fi = to_model_ref(m)->get_func_interp(to_func_decl(f));
|
||||
if (!_fi) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
Z3_func_interp_ref * fi = alloc(Z3_func_interp_ref, to_model_ref(m));
|
||||
fi->m_func_interp = _fi;
|
||||
mk_c(c)->save_object(fi);
|
||||
RETURN_Z3(of_func_interp(fi));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
unsigned Z3_API Z3_model_get_num_consts(Z3_context c, Z3_model m) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_model_get_num_consts(c, m);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_NON_NULL(m, 0);
|
||||
return to_model_ref(m)->get_num_constants();
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_func_decl Z3_API Z3_model_get_const_decl(Z3_context c, Z3_model m, unsigned i) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_model_get_const_decl(c, m, i);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_NON_NULL(m, 0);
|
||||
model * _m = to_model_ref(m);
|
||||
if (i < _m->get_num_constants()) {
|
||||
RETURN_Z3(of_func_decl(_m->get_constant(i)));
|
||||
}
|
||||
else {
|
||||
SET_ERROR_CODE(Z3_IOB);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
unsigned Z3_API Z3_model_get_num_funcs(Z3_context c, Z3_model m) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_model_get_num_funcs(c, m);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_NON_NULL(m, 0);
|
||||
return to_model_ref(m)->get_num_functions();
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_func_decl get_model_func_decl_core(Z3_context c, Z3_model m, unsigned i) {
|
||||
CHECK_NON_NULL(m, 0);
|
||||
model * _m = to_model_ref(m);
|
||||
if (i >= _m->get_num_functions()) {
|
||||
SET_ERROR_CODE(Z3_IOB);
|
||||
return 0;
|
||||
}
|
||||
return of_func_decl(_m->get_function(i));
|
||||
}
|
||||
|
||||
Z3_func_decl Z3_API Z3_model_get_func_decl(Z3_context c, Z3_model m, unsigned i) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_model_func_decl(c, m, i);
|
||||
RESET_ERROR_CODE();
|
||||
Z3_func_decl r = get_model_func_decl_core(c, m, i);
|
||||
RETURN_Z3(r);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_bool Z3_API Z3_model_eval(Z3_context c, Z3_model m, Z3_ast t, Z3_bool model_completion, Z3_ast * v) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_model_eval(c, m, t, model_completion, v);
|
||||
if (v) *v = 0;
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_NON_NULL(m, Z3_FALSE);
|
||||
model * _m = to_model_ref(m);
|
||||
expr_ref result(mk_c(c)->m());
|
||||
_m->eval(to_expr(t), result, model_completion == Z3_TRUE);
|
||||
mk_c(c)->save_ast_trail(result.get());
|
||||
*v = of_ast(result.get());
|
||||
RETURN_Z3_model_eval Z3_TRUE;
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
unsigned Z3_API Z3_model_get_num_sorts(Z3_context c, Z3_model m) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_model_get_num_sorts(c, m);
|
||||
RESET_ERROR_CODE();
|
||||
return to_model_ref(m)->get_num_uninterpreted_sorts();
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_sort Z3_API Z3_model_get_sort(Z3_context c, Z3_model m, unsigned i) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_model_get_sort(c, m, i);
|
||||
RESET_ERROR_CODE();
|
||||
if (i >= to_model_ref(m)->get_num_uninterpreted_sorts()) {
|
||||
SET_ERROR_CODE(Z3_IOB);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
sort * s = to_model_ref(m)->get_uninterpreted_sort(i);
|
||||
RETURN_Z3(of_sort(s));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast_vector Z3_API Z3_model_get_sort_universe(Z3_context c, Z3_model m, Z3_sort s) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_model_get_sort_universe(c, m, s);
|
||||
RESET_ERROR_CODE();
|
||||
if (!to_model_ref(m)->has_uninterpreted_sort(to_sort(s))) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
ptr_vector<expr> const & universe = to_model_ref(m)->get_universe(to_sort(s));
|
||||
Z3_ast_vector_ref * v = alloc(Z3_ast_vector_ref, mk_c(c)->m());
|
||||
mk_c(c)->save_object(v);
|
||||
unsigned sz = universe.size();
|
||||
for (unsigned i = 0; i < sz; i++) {
|
||||
v->m_ast_vector.push_back(universe[i]);
|
||||
}
|
||||
RETURN_Z3(of_ast_vector(v));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_bool Z3_API Z3_is_as_array(Z3_context c, Z3_ast a) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_is_as_array(c, a);
|
||||
RESET_ERROR_CODE();
|
||||
return is_expr(to_ast(a)) && is_app_of(to_expr(a), mk_c(c)->get_array_fid(), OP_AS_ARRAY);
|
||||
Z3_CATCH_RETURN(Z3_FALSE);
|
||||
}
|
||||
|
||||
Z3_func_decl Z3_API Z3_get_as_array_func_decl(Z3_context c, Z3_ast a) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_as_array_func_decl(c, a);
|
||||
RESET_ERROR_CODE();
|
||||
if (is_expr(to_ast(a)) && is_app_of(to_expr(a), mk_c(c)->get_array_fid(), OP_AS_ARRAY)) {
|
||||
return of_func_decl(to_func_decl(to_app(a)->get_decl()->get_parameter(0).get_ast()));
|
||||
}
|
||||
else {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
void Z3_API Z3_func_interp_inc_ref(Z3_context c, Z3_func_interp f) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_func_interp_inc_ref(c, f);
|
||||
RESET_ERROR_CODE();
|
||||
if (f) {
|
||||
to_func_interp(f)->inc_ref();
|
||||
}
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_func_interp_dec_ref(Z3_context c, Z3_func_interp f) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_func_interp_dec_ref(c, f);
|
||||
RESET_ERROR_CODE();
|
||||
if (f) {
|
||||
to_func_interp(f)->dec_ref();
|
||||
}
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
unsigned Z3_API Z3_func_interp_get_num_entries(Z3_context c, Z3_func_interp f) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_func_interp_get_num_entries(c, f);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_NON_NULL(f, 0);
|
||||
return to_func_interp_ref(f)->num_entries();
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_func_entry Z3_API Z3_func_interp_get_entry(Z3_context c, Z3_func_interp f, unsigned i) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_func_interp_get_entry(c, f, i);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_NON_NULL(f, 0);
|
||||
if (i >= to_func_interp_ref(f)->num_entries()) {
|
||||
SET_ERROR_CODE(Z3_IOB);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
Z3_func_entry_ref * e = alloc(Z3_func_entry_ref, to_func_interp(f)->m_model.get());
|
||||
e->m_func_interp = to_func_interp_ref(f);
|
||||
e->m_func_entry = to_func_interp_ref(f)->get_entry(i);
|
||||
mk_c(c)->save_object(e);
|
||||
RETURN_Z3(of_func_entry(e));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_func_interp_get_else(Z3_context c, Z3_func_interp f) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_func_interp_get_else(c, f);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_NON_NULL(f, 0);
|
||||
expr * e = to_func_interp_ref(f)->get_else();
|
||||
RETURN_Z3(of_expr(e));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
unsigned Z3_API Z3_func_interp_get_arity(Z3_context c, Z3_func_interp f) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_func_interp_get_arity(c, f);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_NON_NULL(f, 0);
|
||||
return to_func_interp_ref(f)->get_arity();
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
void Z3_API Z3_func_entry_inc_ref(Z3_context c, Z3_func_entry e) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_func_entry_inc_ref(c, e);
|
||||
RESET_ERROR_CODE();
|
||||
if (e) {
|
||||
to_func_entry(e)->inc_ref();
|
||||
}
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_func_entry_dec_ref(Z3_context c, Z3_func_entry e) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_func_entry_dec_ref(c, e);
|
||||
RESET_ERROR_CODE();
|
||||
if (e) {
|
||||
to_func_entry(e)->dec_ref();
|
||||
}
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_func_entry_get_value(Z3_context c, Z3_func_entry e) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_func_entry_get_value(c, e);
|
||||
RESET_ERROR_CODE();
|
||||
expr * v = to_func_entry_ref(e)->get_result();
|
||||
RETURN_Z3(of_expr(v));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
unsigned Z3_API Z3_func_entry_get_num_args(Z3_context c, Z3_func_entry e) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_func_entry_get_num_args(c, e);
|
||||
RESET_ERROR_CODE();
|
||||
return to_func_entry(e)->m_func_interp->get_arity();
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_func_entry_get_arg(Z3_context c, Z3_func_entry e, unsigned i) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_func_entry_get_arg(c, e, i);
|
||||
RESET_ERROR_CODE();
|
||||
if (i >= to_func_entry(e)->m_func_interp->get_arity()) {
|
||||
SET_ERROR_CODE(Z3_IOB);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
expr * r = to_func_entry(e)->m_func_entry->get_arg(i);
|
||||
RETURN_Z3(of_expr(r));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
// ----------------------------
|
||||
//
|
||||
// DEPRECATED API
|
||||
//
|
||||
// ----------------------------
|
||||
|
||||
void Z3_API Z3_del_model(Z3_context c, Z3_model m) {
|
||||
Z3_model_dec_ref(c, m);
|
||||
}
|
||||
|
||||
unsigned Z3_API Z3_get_model_num_constants(Z3_context c, Z3_model m) {
|
||||
return Z3_model_get_num_consts(c, m);
|
||||
}
|
||||
|
||||
Z3_func_decl Z3_API Z3_get_model_constant(Z3_context c, Z3_model m, unsigned i) {
|
||||
return Z3_model_get_const_decl(c, m, i);
|
||||
}
|
||||
|
||||
unsigned Z3_API Z3_get_model_num_funcs(Z3_context c, Z3_model m) {
|
||||
return Z3_model_get_num_funcs(c, m);
|
||||
}
|
||||
|
||||
Z3_func_decl Z3_API Z3_get_model_func_decl(Z3_context c, Z3_model m, unsigned i) {
|
||||
return Z3_model_get_func_decl(c, m, i);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_get_model_func_else(Z3_context c, Z3_model m, unsigned i) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_model_func_else(c, m, i);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_NON_NULL(m, 0);
|
||||
Z3_func_decl d = get_model_func_decl_core(c, m, i);
|
||||
if (d) {
|
||||
model * _m = to_model_ref(m);
|
||||
func_interp * g = _m->get_func_interp(to_func_decl(d));
|
||||
if (g) {
|
||||
expr * e = g->get_else();
|
||||
mk_c(c)->save_ast_trail(e);
|
||||
RETURN_Z3(of_ast(e));
|
||||
}
|
||||
SET_ERROR_CODE(Z3_IOB);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
RETURN_Z3(0);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
unsigned get_model_func_num_entries_core(Z3_context c, Z3_model m, unsigned i) {
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_NON_NULL(m, 0);
|
||||
Z3_func_decl d = get_model_func_decl_core(c, m, i);
|
||||
if (d) {
|
||||
model * _m = to_model_ref(m);
|
||||
func_interp * g = _m->get_func_interp(to_func_decl(d));
|
||||
if (g) {
|
||||
return g->num_entries();
|
||||
}
|
||||
SET_ERROR_CODE(Z3_IOB);
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned Z3_API Z3_get_model_func_num_entries(Z3_context c, Z3_model m, unsigned i) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_model_func_num_entries(c, m, i);
|
||||
return get_model_func_num_entries_core(c, m, i);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
unsigned get_model_func_entry_num_args_core(Z3_context c,
|
||||
Z3_model m,
|
||||
unsigned i,
|
||||
unsigned j) {
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_NON_NULL(m, 0);
|
||||
if (j >= get_model_func_num_entries_core(c, m, i)) {
|
||||
SET_ERROR_CODE(Z3_IOB);
|
||||
return 0;
|
||||
}
|
||||
Z3_func_decl d = get_model_func_decl_core(c, m, i);
|
||||
if (d) {
|
||||
model * _m = to_model_ref(m);
|
||||
func_interp * g = _m->get_func_interp(to_func_decl(d));
|
||||
return g->get_arity();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned Z3_API Z3_get_model_func_entry_num_args(Z3_context c,
|
||||
Z3_model m,
|
||||
unsigned i,
|
||||
unsigned j) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_model_func_entry_num_args(c, m, i, j);
|
||||
return get_model_func_entry_num_args_core(c, m, i, j);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_get_model_func_entry_arg(Z3_context c,
|
||||
Z3_model m,
|
||||
unsigned i,
|
||||
unsigned j,
|
||||
unsigned k) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_model_func_entry_arg(c, m, i, j, k);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_NON_NULL(m, 0);
|
||||
if (j >= get_model_func_num_entries_core(c, m, i) || k >= get_model_func_entry_num_args_core(c, m, i, j)) {
|
||||
SET_ERROR_CODE(Z3_IOB);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
Z3_func_decl d = get_model_func_decl_core(c, m, i);
|
||||
if (d) {
|
||||
model * _m = to_model_ref(m);
|
||||
func_interp * g = _m->get_func_interp(to_func_decl(d));
|
||||
if (g && j < g->num_entries()) {
|
||||
func_entry const * e = g->get_entry(j);
|
||||
if (k < g->get_arity()) {
|
||||
expr * a = e->get_arg(k);
|
||||
mk_c(c)->save_ast_trail(a);
|
||||
RETURN_Z3(of_ast(a));
|
||||
}
|
||||
}
|
||||
SET_ERROR_CODE(Z3_IOB);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
RETURN_Z3(0);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_get_model_func_entry_value(Z3_context c,
|
||||
Z3_model m,
|
||||
unsigned i,
|
||||
unsigned j) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_model_func_entry_value(c, m, i, j);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_NON_NULL(m, 0);
|
||||
if (j >= get_model_func_num_entries_core(c, m, i)) {
|
||||
SET_ERROR_CODE(Z3_IOB);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
Z3_func_decl d = get_model_func_decl_core(c, m, i);
|
||||
if (d) {
|
||||
model * _m = to_model_ref(m);
|
||||
func_interp * g = _m->get_func_interp(to_func_decl(d));
|
||||
if (g && j < g->num_entries()) {
|
||||
func_entry const* e = g->get_entry(j);
|
||||
expr* a = e->get_result();
|
||||
mk_c(c)->save_ast_trail(a);
|
||||
RETURN_Z3(of_ast(a));
|
||||
}
|
||||
SET_ERROR_CODE(Z3_IOB);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
RETURN_Z3(0);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_bool Z3_API Z3_eval(Z3_context c,
|
||||
Z3_model m,
|
||||
Z3_ast t,
|
||||
Z3_ast * v) {
|
||||
return Z3_model_eval(c, m, t, mk_c(c)->fparams().m_model_completion, v);
|
||||
}
|
||||
|
||||
Z3_bool Z3_API Z3_eval_func_decl(Z3_context c,
|
||||
Z3_model m,
|
||||
Z3_func_decl decl,
|
||||
Z3_ast* v) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_eval_func_decl(c, m, decl, v);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_NON_NULL(m, Z3_FALSE);
|
||||
ast_manager & mgr = mk_c(c)->m();
|
||||
model * _m = to_model_ref(m);
|
||||
expr_ref result(mgr);
|
||||
if( _m->eval(to_func_decl(decl), result)) {
|
||||
mk_c(c)->save_ast_trail(result.get());
|
||||
*v = of_ast(result.get());
|
||||
RETURN_Z3_eval_func_decl Z3_TRUE;
|
||||
}
|
||||
else {
|
||||
return Z3_FALSE;
|
||||
}
|
||||
Z3_CATCH_RETURN(Z3_FALSE);
|
||||
}
|
||||
|
||||
|
||||
Z3_bool Z3_API Z3_is_array_value(Z3_context c, Z3_model _m, Z3_ast _v, unsigned* size) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_is_array_value(c, _m, _v, size);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_NON_NULL(_v, Z3_FALSE);
|
||||
CHECK_NON_NULL(_m, Z3_FALSE);
|
||||
model * m = to_model_ref(_m);
|
||||
expr * v = to_expr(_v);
|
||||
ast_manager& mgr = mk_c(c)->m();
|
||||
family_id afid = mk_c(c)->get_array_fid();
|
||||
unsigned sz = 0;
|
||||
array_util pl(mgr);
|
||||
if (pl.is_as_array(v)) {
|
||||
func_decl* f = pl.get_as_array_func_decl(to_app(v));
|
||||
func_interp* g = m->get_func_interp(f);
|
||||
sz = g->num_entries();
|
||||
if (sz > 0 && g->get_arity() != 1) {
|
||||
return Z3_FALSE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
while (pl.is_store(v)) {
|
||||
if (to_app(v)->get_num_args() != 3) {
|
||||
return Z3_FALSE;
|
||||
}
|
||||
v = to_app(v)->get_arg(0);
|
||||
++sz;
|
||||
}
|
||||
if (!is_app_of(v, afid, OP_CONST_ARRAY)) {
|
||||
return Z3_FALSE;
|
||||
}
|
||||
}
|
||||
if (size) {
|
||||
*size = sz;
|
||||
}
|
||||
return Z3_TRUE;
|
||||
Z3_CATCH_RETURN(Z3_FALSE);
|
||||
}
|
||||
|
||||
|
||||
void Z3_API Z3_get_array_value(Z3_context c,
|
||||
Z3_model _m,
|
||||
Z3_ast _v,
|
||||
unsigned num_entries,
|
||||
Z3_ast indices[],
|
||||
Z3_ast values[],
|
||||
Z3_ast* else_value) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_array_value(c, _m, _v, num_entries, indices, values, else_value);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_NON_NULL(_m, );
|
||||
model * m = to_model_ref(_m);
|
||||
|
||||
expr* v = to_expr(_v);
|
||||
family_id afid = mk_c(c)->get_array_fid();
|
||||
ast_manager& mgr = mk_c(c)->m();
|
||||
array_util pl(mgr);
|
||||
|
||||
//
|
||||
// note: _v is already reference counted.
|
||||
// saving the trail for the returned values
|
||||
// is redundant.
|
||||
//
|
||||
unsigned sz = 0;
|
||||
if (pl.is_as_array(v)) {
|
||||
func_decl* f = pl.get_as_array_func_decl(to_app(v));
|
||||
func_interp* g = m->get_func_interp(f);
|
||||
sz = g->num_entries();
|
||||
if (g->get_arity() != 1) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
return;
|
||||
}
|
||||
for (unsigned i = 0; i < sz && i < num_entries; ++i) {
|
||||
indices[i] = of_ast(g->get_entry(i)->get_arg(0));
|
||||
values[i] = of_ast(g->get_entry(i)->get_result());
|
||||
}
|
||||
if (else_value) {
|
||||
*else_value = of_ast(g->get_else());
|
||||
}
|
||||
}
|
||||
else {
|
||||
while (sz <= num_entries && is_app_of(v, afid, OP_STORE)) {
|
||||
app* a = to_app(v);
|
||||
if (a->get_num_args() != 3) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
return;
|
||||
}
|
||||
expr* idx = a->get_arg(1);
|
||||
expr* val = a->get_arg(2);
|
||||
indices[sz] = of_ast(idx);
|
||||
values[sz] = of_ast(val);
|
||||
v = to_app(v)->get_arg(0);
|
||||
++sz;
|
||||
}
|
||||
|
||||
if (is_app_of(v, afid, OP_CONST_ARRAY)) {
|
||||
if (else_value) {
|
||||
*else_value = of_ast(to_app(v)->get_arg(0));
|
||||
}
|
||||
}
|
||||
else {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
return;
|
||||
}
|
||||
}
|
||||
RETURN_Z3_get_array_value;
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
Z3_bool Z3_API Z3_eval_decl(Z3_context c,
|
||||
Z3_model m,
|
||||
Z3_func_decl d,
|
||||
unsigned num_args,
|
||||
Z3_ast const args[],
|
||||
Z3_ast* v) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_eval_decl(c, m, d, num_args, args, v);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_NON_NULL(m, Z3_FALSE);
|
||||
ast_manager & mgr = mk_c(c)->m();
|
||||
model * _m = to_model_ref(m);
|
||||
app_ref app(mgr);
|
||||
app = mgr.mk_app(to_func_decl(d), num_args, to_exprs(args));
|
||||
expr_ref result(mgr);
|
||||
_m->eval(app.get(), result);
|
||||
mk_c(c)->save_ast_trail(result.get());
|
||||
*v = of_ast(result.get());
|
||||
RETURN_Z3_eval_decl Z3_TRUE;
|
||||
Z3_CATCH_RETURN(Z3_FALSE);
|
||||
}
|
||||
|
||||
char const * Z3_API Z3_model_to_string(Z3_context c, Z3_model m) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_model_to_string(c, m);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_NON_NULL(m, 0);
|
||||
std::ostringstream buffer;
|
||||
std::string result;
|
||||
if (mk_c(c)->get_print_mode() == Z3_PRINT_SMTLIB2_COMPLIANT) {
|
||||
model_smt2_pp(buffer, mk_c(c)->m(), *(to_model_ref(m)), 0);
|
||||
// Hack for removing the trailing '\n'
|
||||
result = buffer.str();
|
||||
if (result.size() != 0)
|
||||
result.resize(result.size()-1);
|
||||
}
|
||||
else {
|
||||
model_v2_pp(buffer, *(to_model_ref(m)), mk_c(c)->fparams().m_model_partial);
|
||||
result = buffer.str();
|
||||
}
|
||||
return mk_c(c)->mk_external_string(result);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
};
|
58
src/api/api_model.h
Normal file
58
src/api/api_model.h
Normal file
|
@ -0,0 +1,58 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
api_model.h
|
||||
|
||||
Abstract:
|
||||
API for models
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2012-03-08.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _API_MODEL_H_
|
||||
#define _API_MODEL_H_
|
||||
|
||||
#include"api_util.h"
|
||||
#include"model.h"
|
||||
|
||||
struct Z3_model_ref : public api::object {
|
||||
model_ref m_model;
|
||||
Z3_model_ref() {}
|
||||
virtual ~Z3_model_ref() {}
|
||||
};
|
||||
|
||||
inline Z3_model_ref * to_model(Z3_model s) { return reinterpret_cast<Z3_model_ref *>(s); }
|
||||
inline Z3_model of_model(Z3_model_ref * s) { return reinterpret_cast<Z3_model>(s); }
|
||||
inline model * to_model_ref(Z3_model s) { return to_model(s)->m_model.get(); }
|
||||
|
||||
struct Z3_func_interp_ref : public api::object {
|
||||
model_ref m_model; // must have it to prevent reference to m_func_interp to be killed.
|
||||
func_interp * m_func_interp;
|
||||
Z3_func_interp_ref(model * m):m_model(m), m_func_interp(0) {}
|
||||
virtual ~Z3_func_interp_ref() {}
|
||||
};
|
||||
|
||||
inline Z3_func_interp_ref * to_func_interp(Z3_func_interp s) { return reinterpret_cast<Z3_func_interp_ref *>(s); }
|
||||
inline Z3_func_interp of_func_interp(Z3_func_interp_ref * s) { return reinterpret_cast<Z3_func_interp>(s); }
|
||||
inline func_interp * to_func_interp_ref(Z3_func_interp s) { return to_func_interp(s)->m_func_interp; }
|
||||
|
||||
struct Z3_func_entry_ref : public api::object {
|
||||
model_ref m_model; // must have it to prevent reference to m_func_entry to be killed.
|
||||
func_interp * m_func_interp;
|
||||
func_entry const * m_func_entry;
|
||||
Z3_func_entry_ref(model * m):m_model(m), m_func_interp(0), m_func_entry(0) {}
|
||||
virtual ~Z3_func_entry_ref() {}
|
||||
};
|
||||
|
||||
inline Z3_func_entry_ref * to_func_entry(Z3_func_entry s) { return reinterpret_cast<Z3_func_entry_ref *>(s); }
|
||||
inline Z3_func_entry of_func_entry(Z3_func_entry_ref * s) { return reinterpret_cast<Z3_func_entry>(s); }
|
||||
inline func_entry const * to_func_entry_ref(Z3_func_entry s) { return to_func_entry(s)->m_func_entry; }
|
||||
|
||||
|
||||
#endif
|
340
src/api/api_numeral.cpp
Normal file
340
src/api/api_numeral.cpp
Normal file
|
@ -0,0 +1,340 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
api_numeral.cpp
|
||||
|
||||
Abstract:
|
||||
API for handling numerals in Z3
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2012-02-29.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include<iostream>
|
||||
#include"z3.h"
|
||||
#include"api_log_macros.h"
|
||||
#include"api_context.h"
|
||||
#include"api_util.h"
|
||||
#include"arith_decl_plugin.h"
|
||||
#include"bv_decl_plugin.h"
|
||||
#include"algebraic_numbers.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
bool is_numeral_sort(Z3_context c, Z3_sort ty) {
|
||||
sort * _ty = to_sort(ty);
|
||||
family_id fid = _ty->get_family_id();
|
||||
if (fid != mk_c(c)->get_arith_fid() &&
|
||||
fid != mk_c(c)->get_bv_fid() &&
|
||||
fid != mk_c(c)->get_datalog_fid()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool check_numeral_sort(Z3_context c, Z3_sort ty) {
|
||||
bool is_num = is_numeral_sort(c, ty);
|
||||
if (!is_num) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
}
|
||||
return is_num;
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_mk_numeral(Z3_context c, const char* n, Z3_sort ty) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_numeral(c, n, ty);
|
||||
RESET_ERROR_CODE();
|
||||
if (!check_numeral_sort(c, ty)) {
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
if (!n) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
std::string fixed_num;
|
||||
char const* m = n;
|
||||
while (*m) {
|
||||
if (!(('0' <= *m && *m <= '9') ||
|
||||
('/' == *m) || ('-' == *m) ||
|
||||
(' ' == *m) || ('\n' == *m) ||
|
||||
('.' == *m) || ('e' == *m) ||
|
||||
('E' == *m))) {
|
||||
SET_ERROR_CODE(Z3_PARSER_ERROR);
|
||||
return 0;
|
||||
}
|
||||
++m;
|
||||
}
|
||||
ast * a = mk_c(c)->mk_numeral_core(rational(n), to_sort(ty));
|
||||
RETURN_Z3(of_ast(a));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_mk_int(Z3_context c, int value, Z3_sort ty) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_int(c, value, ty);
|
||||
RESET_ERROR_CODE();
|
||||
if (!check_numeral_sort(c, ty)) {
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
ast * a = mk_c(c)->mk_numeral_core(rational(value), to_sort(ty));
|
||||
RETURN_Z3(of_ast(a));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_mk_unsigned_int(Z3_context c, unsigned value, Z3_sort ty) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_unsigned_int(c, value, ty);
|
||||
RESET_ERROR_CODE();
|
||||
if (!check_numeral_sort(c, ty)) {
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
ast * a = mk_c(c)->mk_numeral_core(rational(value), to_sort(ty));
|
||||
RETURN_Z3(of_ast(a));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_mk_int64(Z3_context c, long long value, Z3_sort ty) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_int64(c, value, ty);
|
||||
RESET_ERROR_CODE();
|
||||
if (!check_numeral_sort(c, ty)) {
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
rational n(value, rational::i64());
|
||||
ast* a = mk_c(c)->mk_numeral_core(n, to_sort(ty));
|
||||
RETURN_Z3(of_ast(a));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_mk_unsigned_int64(Z3_context c, unsigned long long value, Z3_sort ty) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_unsigned_int64(c, value, ty);
|
||||
RESET_ERROR_CODE();
|
||||
if (!check_numeral_sort(c, ty)) {
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
rational n(value, rational::ui64());
|
||||
ast * a = mk_c(c)->mk_numeral_core(n, to_sort(ty));
|
||||
RETURN_Z3(of_ast(a));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_bool Z3_API Z3_is_numeral_ast(Z3_context c, Z3_ast a) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_is_numeral_ast(c, a);
|
||||
RESET_ERROR_CODE();
|
||||
expr* e = to_expr(a);
|
||||
return
|
||||
mk_c(c)->autil().is_numeral(e) ||
|
||||
mk_c(c)->bvutil().is_numeral(e);
|
||||
Z3_CATCH_RETURN(Z3_FALSE);
|
||||
}
|
||||
|
||||
Z3_bool Z3_API Z3_get_numeral_rational(Z3_context c, Z3_ast a, rational& r) {
|
||||
Z3_TRY;
|
||||
// This function is not part of the public API
|
||||
RESET_ERROR_CODE();
|
||||
expr* e = to_expr(a);
|
||||
if (!e) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
return Z3_FALSE;
|
||||
}
|
||||
if (mk_c(c)->autil().is_numeral(e, r)) {
|
||||
return Z3_TRUE;
|
||||
}
|
||||
unsigned bv_size;
|
||||
if (mk_c(c)->bvutil().is_numeral(e, r, bv_size)) {
|
||||
return Z3_TRUE;
|
||||
}
|
||||
uint64 v;
|
||||
if (mk_c(c)->datalog_util().is_numeral(e, v)) {
|
||||
r = rational(v, rational::ui64());
|
||||
return Z3_TRUE;
|
||||
}
|
||||
return Z3_FALSE;
|
||||
Z3_CATCH_RETURN(Z3_FALSE);
|
||||
}
|
||||
|
||||
|
||||
Z3_string Z3_API Z3_get_numeral_string(Z3_context c, Z3_ast a) {
|
||||
Z3_TRY;
|
||||
// This function invokes Z3_get_numeral_rational, but it is still ok to add LOG command here because it does not return a Z3 object.
|
||||
LOG_Z3_get_numeral_string(c, a);
|
||||
RESET_ERROR_CODE();
|
||||
rational r;
|
||||
Z3_bool ok = Z3_get_numeral_rational(c, a, r);
|
||||
if (ok == Z3_TRUE) {
|
||||
return mk_c(c)->mk_external_string(r.to_string());
|
||||
}
|
||||
else {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
return "";
|
||||
}
|
||||
Z3_CATCH_RETURN("");
|
||||
}
|
||||
|
||||
Z3_string Z3_API Z3_get_numeral_decimal_string(Z3_context c, Z3_ast a, unsigned precision) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_numeral_decimal_string(c, a, precision);
|
||||
RESET_ERROR_CODE();
|
||||
expr* e = to_expr(a);
|
||||
if (!e) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
return "";
|
||||
}
|
||||
rational r;
|
||||
arith_util & u = mk_c(c)->autil();
|
||||
if (u.is_numeral(e, r) && !r.is_int()) {
|
||||
std::ostringstream buffer;
|
||||
r.display_decimal(buffer, precision);
|
||||
return mk_c(c)->mk_external_string(buffer.str());
|
||||
}
|
||||
if (u.is_irrational_algebraic_numeral(e)) {
|
||||
algebraic_numbers::anum const & n = u.to_irrational_algebraic_numeral(e);
|
||||
algebraic_numbers::manager & am = u.am();
|
||||
std::ostringstream buffer;
|
||||
am.display_decimal(buffer, n, precision);
|
||||
return mk_c(c)->mk_external_string(buffer.str());
|
||||
}
|
||||
Z3_bool ok = Z3_get_numeral_rational(c, a, r);
|
||||
if (ok == Z3_TRUE) {
|
||||
return mk_c(c)->mk_external_string(r.to_string());
|
||||
}
|
||||
else {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
return "";
|
||||
}
|
||||
Z3_CATCH_RETURN("");
|
||||
}
|
||||
|
||||
Z3_bool Z3_API Z3_get_numeral_small(Z3_context c, Z3_ast a, long long* num, long long* den) {
|
||||
Z3_TRY;
|
||||
// This function invokes Z3_get_numeral_rational, but it is still ok to add LOG command here because it does not return a Z3 object.
|
||||
LOG_Z3_get_numeral_small(c, a, num, den);
|
||||
RESET_ERROR_CODE();
|
||||
rational r;
|
||||
Z3_bool ok = Z3_get_numeral_rational(c, a, r);
|
||||
if (ok == Z3_TRUE) {
|
||||
rational n = numerator(r);
|
||||
rational d = denominator(r);
|
||||
if (n.is_int64() && d.is_int64()) {
|
||||
*num = n.get_int64();
|
||||
*den = d.get_int64();
|
||||
return Z3_TRUE;
|
||||
}
|
||||
else {
|
||||
return Z3_FALSE;
|
||||
}
|
||||
}
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
return Z3_FALSE;
|
||||
Z3_CATCH_RETURN(Z3_FALSE);
|
||||
}
|
||||
|
||||
|
||||
Z3_bool Z3_API Z3_get_numeral_int(Z3_context c, Z3_ast v, int* i) {
|
||||
Z3_TRY;
|
||||
// This function invokes Z3_get_numeral_int64, but it is still ok to add LOG command here because it does not return a Z3 object.
|
||||
LOG_Z3_get_numeral_int(c, v, i);
|
||||
RESET_ERROR_CODE();
|
||||
if (!i) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
return Z3_FALSE;
|
||||
}
|
||||
long long l;
|
||||
if (Z3_get_numeral_int64(c, v, &l) && l >= INT_MIN && l <= INT_MAX) {
|
||||
*i = static_cast<int>(l);
|
||||
return Z3_TRUE;
|
||||
}
|
||||
return Z3_FALSE;
|
||||
Z3_CATCH_RETURN(Z3_FALSE);
|
||||
}
|
||||
|
||||
Z3_bool Z3_API Z3_get_numeral_uint(Z3_context c, Z3_ast v, unsigned* u) {
|
||||
Z3_TRY;
|
||||
// This function invokes Z3_get_numeral_uint64, but it is still ok to add LOG command here because it does not return a Z3 object.
|
||||
LOG_Z3_get_numeral_uint(c, v, u);
|
||||
RESET_ERROR_CODE();
|
||||
if (!u) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
return Z3_FALSE;
|
||||
}
|
||||
unsigned long long l;
|
||||
if (Z3_get_numeral_uint64(c, v, &l) && (l <= 0xFFFFFFFF)) {
|
||||
*u = static_cast<unsigned>(l);
|
||||
return Z3_TRUE;
|
||||
}
|
||||
return Z3_FALSE;
|
||||
Z3_CATCH_RETURN(Z3_FALSE);
|
||||
}
|
||||
|
||||
Z3_bool Z3_API Z3_get_numeral_uint64(Z3_context c, Z3_ast v, unsigned long long* u) {
|
||||
Z3_TRY;
|
||||
// This function invokes Z3_get_numeral_rational, but it is still ok to add LOG command here because it does not return a Z3 object.
|
||||
LOG_Z3_get_numeral_uint64(c, v, u);
|
||||
RESET_ERROR_CODE();
|
||||
if (!u) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
return Z3_FALSE;
|
||||
}
|
||||
rational r;
|
||||
Z3_bool ok = Z3_get_numeral_rational(c, v, r);
|
||||
SASSERT(u);
|
||||
if (ok == Z3_TRUE && r.is_uint64()) {
|
||||
*u = r.get_uint64();
|
||||
return ok;
|
||||
}
|
||||
return Z3_FALSE;
|
||||
Z3_CATCH_RETURN(Z3_FALSE);
|
||||
}
|
||||
|
||||
Z3_bool Z3_API Z3_get_numeral_int64(Z3_context c, Z3_ast v, long long* i) {
|
||||
Z3_TRY;
|
||||
// This function invokes Z3_get_numeral_rational, but it is still ok to add LOG command here because it does not return a Z3 object.
|
||||
LOG_Z3_get_numeral_int64(c, v, i);
|
||||
RESET_ERROR_CODE();
|
||||
if (!i) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
return Z3_FALSE;
|
||||
}
|
||||
rational r;
|
||||
Z3_bool ok = Z3_get_numeral_rational(c, v, r);
|
||||
if (ok == Z3_TRUE && r.is_int64()) {
|
||||
*i = r.get_int64();
|
||||
return ok;
|
||||
}
|
||||
return Z3_FALSE;
|
||||
Z3_CATCH_RETURN(Z3_FALSE);
|
||||
}
|
||||
|
||||
Z3_bool Z3_API Z3_get_numeral_rational_int64(Z3_context c, Z3_ast v, long long* num, long long* den) {
|
||||
Z3_TRY;
|
||||
// This function invokes Z3_get_numeral_rational, but it is still ok to add LOG command here because it does not return a Z3 object.
|
||||
LOG_Z3_get_numeral_rational_int64(c, v, num, den);
|
||||
RESET_ERROR_CODE();
|
||||
if (!num || !den) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
return Z3_FALSE;
|
||||
}
|
||||
rational r;
|
||||
Z3_bool ok = Z3_get_numeral_rational(c, v, r);
|
||||
if (ok != Z3_TRUE) {
|
||||
return ok;
|
||||
}
|
||||
rational n = numerator(r);
|
||||
rational d = denominator(r);
|
||||
if (n.is_int64() && d.is_int64()) {
|
||||
*num = n.get_int64();
|
||||
*den = d.get_int64();
|
||||
return ok;
|
||||
}
|
||||
return Z3_FALSE;
|
||||
Z3_CATCH_RETURN(Z3_FALSE);
|
||||
}
|
||||
|
||||
};
|
199
src/api/api_params.cpp
Normal file
199
src/api/api_params.cpp
Normal 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
426
src/api/api_parsers.cpp
Normal file
|
@ -0,0 +1,426 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
api_parsers.cpp
|
||||
|
||||
Abstract:
|
||||
API for parsing different formats
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2012-02-29.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include<iostream>
|
||||
#include"z3.h"
|
||||
#include"api_log_macros.h"
|
||||
#include"api_context.h"
|
||||
#include"api_util.h"
|
||||
#include"cmd_context.h"
|
||||
#include"smt2parser.h"
|
||||
#include"smtparser.h"
|
||||
#include"z3_solver.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
void init_smtlib_parser(Z3_context c,
|
||||
unsigned num_sorts,
|
||||
Z3_symbol const sort_names[],
|
||||
Z3_sort const types[],
|
||||
unsigned num_decls,
|
||||
Z3_symbol const decl_names[],
|
||||
Z3_func_decl const decls[]) {
|
||||
mk_c(c)->reset_parser();
|
||||
mk_c(c)->m_smtlib_parser = smtlib::parser::create(mk_c(c)->m());
|
||||
mk_c(c)->m_smtlib_parser->initialize_smtlib();
|
||||
smtlib::symtable * table = mk_c(c)->m_smtlib_parser->get_benchmark()->get_symtable();
|
||||
for (unsigned i = 0; i < num_sorts; i++) {
|
||||
table->insert(to_symbol(sort_names[i]), to_sort(types[i]));
|
||||
}
|
||||
for (unsigned i = 0; i < num_decls; i++) {
|
||||
table->insert(to_symbol(decl_names[i]), to_func_decl(decls[i]));
|
||||
}
|
||||
}
|
||||
|
||||
void Z3_API Z3_parse_smtlib_string(Z3_context c,
|
||||
const char * str,
|
||||
unsigned num_sorts,
|
||||
Z3_symbol const sort_names[],
|
||||
Z3_sort const sorts[],
|
||||
unsigned num_decls,
|
||||
Z3_symbol const decl_names[],
|
||||
Z3_func_decl const decls[]) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_parse_smtlib_string(c, str, num_sorts, sort_names, sorts, num_decls, decl_names, decls);
|
||||
std::ostringstream outs;
|
||||
bool ok = false;
|
||||
|
||||
RESET_ERROR_CODE();
|
||||
init_smtlib_parser(c, num_sorts, sort_names, sorts, num_decls, decl_names, decls);
|
||||
mk_c(c)->m_smtlib_parser->set_error_stream(outs);
|
||||
try {
|
||||
ok = mk_c(c)->m_smtlib_parser->parse_string(str);
|
||||
}
|
||||
catch (...) {
|
||||
ok = false;
|
||||
}
|
||||
mk_c(c)->m_smtlib_error_buffer = outs.str();
|
||||
if (!ok) {
|
||||
mk_c(c)->reset_parser();
|
||||
SET_ERROR_CODE(Z3_PARSER_ERROR);
|
||||
}
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_parse_smtlib_file(Z3_context c,
|
||||
const char * file_name,
|
||||
unsigned num_sorts,
|
||||
Z3_symbol const sort_names[],
|
||||
Z3_sort const types[],
|
||||
unsigned num_decls,
|
||||
Z3_symbol const decl_names[],
|
||||
Z3_func_decl const decls[]) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_parse_smtlib_file(c, file_name, num_sorts, sort_names, types, num_decls, decl_names, decls);
|
||||
bool ok = false;
|
||||
RESET_ERROR_CODE();
|
||||
std::ostringstream outs;
|
||||
init_smtlib_parser(c, num_sorts, sort_names, types, num_decls, decl_names, decls);
|
||||
mk_c(c)->m_smtlib_parser->set_error_stream(outs);
|
||||
try {
|
||||
ok = mk_c(c)->m_smtlib_parser->parse_file(file_name);
|
||||
}
|
||||
catch(...) {
|
||||
ok = false;
|
||||
}
|
||||
mk_c(c)->m_smtlib_error_buffer = outs.str();
|
||||
if (!ok) {
|
||||
mk_c(c)->reset_parser();
|
||||
SET_ERROR_CODE(Z3_PARSER_ERROR);
|
||||
}
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
unsigned Z3_API Z3_get_smtlib_num_formulas(Z3_context c) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_smtlib_num_formulas(c);
|
||||
RESET_ERROR_CODE();
|
||||
if (mk_c(c)->m_smtlib_parser) {
|
||||
return mk_c(c)->m_smtlib_parser->get_benchmark()->get_num_formulas();
|
||||
}
|
||||
SET_ERROR_CODE(Z3_NO_PARSER);
|
||||
return 0;
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_get_smtlib_formula(Z3_context c, unsigned i) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_smtlib_formula(c, i);
|
||||
RESET_ERROR_CODE();
|
||||
if (mk_c(c)->m_smtlib_parser) {
|
||||
if (i < mk_c(c)->m_smtlib_parser->get_benchmark()->get_num_formulas()) {
|
||||
ast * f = mk_c(c)->m_smtlib_parser->get_benchmark()->begin_formulas()[i];
|
||||
mk_c(c)->save_ast_trail(f);
|
||||
RETURN_Z3(of_ast(f));
|
||||
}
|
||||
else {
|
||||
SET_ERROR_CODE(Z3_IOB);
|
||||
}
|
||||
}
|
||||
else {
|
||||
SET_ERROR_CODE(Z3_NO_PARSER);
|
||||
}
|
||||
RETURN_Z3(0);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
unsigned Z3_API Z3_get_smtlib_num_assumptions(Z3_context c) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_smtlib_num_assumptions(c);
|
||||
RESET_ERROR_CODE();
|
||||
if (mk_c(c)->m_smtlib_parser) {
|
||||
return mk_c(c)->m_smtlib_parser->get_benchmark()->get_num_axioms();
|
||||
}
|
||||
SET_ERROR_CODE(Z3_NO_PARSER);
|
||||
return 0;
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_get_smtlib_assumption(Z3_context c, unsigned i) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_smtlib_assumption(c, i);
|
||||
RESET_ERROR_CODE();
|
||||
if (mk_c(c)->m_smtlib_parser) {
|
||||
if (i < mk_c(c)->m_smtlib_parser->get_benchmark()->get_num_axioms()) {
|
||||
ast * a = mk_c(c)->m_smtlib_parser->get_benchmark()->begin_axioms()[i];
|
||||
mk_c(c)->save_ast_trail(a);
|
||||
RETURN_Z3(of_ast(a));
|
||||
}
|
||||
else {
|
||||
SET_ERROR_CODE(Z3_IOB);
|
||||
}
|
||||
}
|
||||
else {
|
||||
SET_ERROR_CODE(Z3_NO_PARSER);
|
||||
}
|
||||
RETURN_Z3(0);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
unsigned Z3_API Z3_get_smtlib_num_decls(Z3_context c) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_smtlib_num_decls(c);
|
||||
RESET_ERROR_CODE();
|
||||
if (mk_c(c)->m_smtlib_parser) {
|
||||
mk_c(c)->extract_smtlib_parser_decls();
|
||||
return mk_c(c)->m_smtlib_parser_decls.size();
|
||||
}
|
||||
SET_ERROR_CODE(Z3_NO_PARSER);
|
||||
return 0;
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_func_decl Z3_API Z3_get_smtlib_decl(Z3_context c, unsigned i) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_smtlib_decl(c, i);
|
||||
RESET_ERROR_CODE();
|
||||
mk_c(c)->extract_smtlib_parser_decls();
|
||||
if (mk_c(c)->m_smtlib_parser) {
|
||||
if (i < mk_c(c)->m_smtlib_parser_decls.size()) {
|
||||
func_decl * d = mk_c(c)->m_smtlib_parser_decls[i];
|
||||
mk_c(c)->save_ast_trail(d);
|
||||
RETURN_Z3(of_func_decl(d));
|
||||
}
|
||||
else {
|
||||
SET_ERROR_CODE(Z3_IOB);
|
||||
}
|
||||
}
|
||||
else {
|
||||
SET_ERROR_CODE(Z3_NO_PARSER);
|
||||
}
|
||||
RETURN_Z3(0);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
unsigned Z3_API Z3_get_smtlib_num_sorts(Z3_context c) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_smtlib_num_sorts(c);
|
||||
RESET_ERROR_CODE();
|
||||
if (mk_c(c)->m_smtlib_parser) {
|
||||
mk_c(c)->extract_smtlib_parser_decls();
|
||||
return mk_c(c)->m_smtlib_parser_sorts.size();
|
||||
}
|
||||
SET_ERROR_CODE(Z3_NO_PARSER);
|
||||
return 0;
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_sort Z3_API Z3_get_smtlib_sort(Z3_context c, unsigned i) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_smtlib_sort(c, i);
|
||||
RESET_ERROR_CODE();
|
||||
if (mk_c(c)->m_smtlib_parser) {
|
||||
mk_c(c)->extract_smtlib_parser_decls();
|
||||
if (i < mk_c(c)->m_smtlib_parser_sorts.size()) {
|
||||
sort* s = mk_c(c)->m_smtlib_parser_sorts[i];
|
||||
mk_c(c)->save_ast_trail(s);
|
||||
RETURN_Z3(of_sort(s));
|
||||
}
|
||||
else {
|
||||
SET_ERROR_CODE(Z3_IOB);
|
||||
}
|
||||
}
|
||||
else {
|
||||
SET_ERROR_CODE(Z3_NO_PARSER);
|
||||
}
|
||||
RETURN_Z3(0);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_string Z3_API Z3_get_smtlib_error(Z3_context c) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_smtlib_error(c);
|
||||
RESET_ERROR_CODE();
|
||||
return mk_c(c)->m_smtlib_error_buffer.c_str();
|
||||
Z3_CATCH_RETURN("");
|
||||
}
|
||||
|
||||
Z3_ast parse_z3_stream(Z3_context c, std::istream& is) {
|
||||
z3_solver parser(c, is, verbose_stream(), mk_c(c)->fparams(), false);
|
||||
if (!parser.parse()) {
|
||||
SET_ERROR_CODE(Z3_PARSER_ERROR);
|
||||
return of_ast(mk_c(c)->m().mk_true());
|
||||
}
|
||||
expr_ref_vector assumptions(mk_c(c)->m());
|
||||
parser.get_assumptions(assumptions);
|
||||
return of_ast(mk_c(c)->mk_and(assumptions.size(), assumptions.c_ptr()));
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_parse_z3_string(Z3_context c, Z3_string str) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_parse_z3_string(c, str);
|
||||
std::string s(str);
|
||||
std::istringstream is(s);
|
||||
Z3_ast r = parse_z3_stream(c, is);
|
||||
RETURN_Z3(r);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_parse_z3_file(Z3_context c, Z3_string file_name) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_parse_z3_file(c, file_name);
|
||||
std::ifstream is(file_name);
|
||||
if (!is) {
|
||||
SET_ERROR_CODE(Z3_PARSER_ERROR);
|
||||
return 0;
|
||||
}
|
||||
Z3_ast r = parse_z3_stream(c, is);
|
||||
RETURN_Z3(r);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
// ---------------
|
||||
// Support for SMTLIB2
|
||||
|
||||
class z3_context_solver : public solver {
|
||||
api::context & m_ctx;
|
||||
smt::solver & ctx() const { return m_ctx.get_solver(); }
|
||||
public:
|
||||
virtual ~z3_context_solver() {}
|
||||
z3_context_solver(api::context& c) : m_ctx(c) {}
|
||||
virtual void init(ast_manager & m, symbol const & logic) {}
|
||||
virtual void collect_statistics(statistics & st) const {}
|
||||
virtual void reset() { ctx().reset(); }
|
||||
virtual void assert_expr(expr * t) { ctx().assert_expr(t); }
|
||||
virtual void push() { ctx().push(); }
|
||||
virtual void pop(unsigned n) { ctx().pop(n); }
|
||||
virtual unsigned get_scope_level() const { return ctx().get_scope_level(); }
|
||||
virtual lbool check_sat(unsigned num_assumptions, expr * const * assumptions) {
|
||||
return ctx().check(num_assumptions, assumptions);
|
||||
}
|
||||
virtual void get_unsat_core(ptr_vector<expr> & r) {
|
||||
unsigned sz = ctx().get_unsat_core_size();
|
||||
for (unsigned i = 0; i < sz; i++)
|
||||
r.push_back(ctx().get_unsat_core_expr(i));
|
||||
}
|
||||
virtual void get_model(model_ref & m) { ctx().get_model(m); }
|
||||
virtual proof * get_proof() { return ctx().get_proof(); }
|
||||
virtual std::string reason_unknown() const { return ctx().last_failure_as_string(); }
|
||||
virtual void get_labels(svector<symbol> & r) {
|
||||
buffer<symbol> tmp;
|
||||
ctx().get_relevant_labels(0, tmp);
|
||||
r.append(tmp.size(), tmp.c_ptr());
|
||||
}
|
||||
|
||||
// These are controlled by the main API
|
||||
virtual void set_cancel(bool f) { }
|
||||
void cancel() { set_cancel(true); }
|
||||
void reset_cancel() { set_cancel(false); }
|
||||
virtual void set_progress_callback(progress_callback * callback) {}
|
||||
};
|
||||
|
||||
Z3_ast parse_smtlib2_stream(bool exec, Z3_context c, std::istream& is,
|
||||
unsigned num_sorts,
|
||||
Z3_symbol const sort_names[],
|
||||
Z3_sort const sorts[],
|
||||
unsigned num_decls,
|
||||
Z3_symbol const decl_names[],
|
||||
Z3_func_decl const decls[]) {
|
||||
Z3_TRY;
|
||||
cmd_context ctx(mk_c(c)->fparams(), false, &(mk_c(c)->m()));
|
||||
ctx.set_ignore_check(true);
|
||||
if (exec) {
|
||||
ctx.set_solver(alloc(z3_context_solver, *mk_c(c)));
|
||||
}
|
||||
for (unsigned i = 0; i < num_decls; ++i) {
|
||||
ctx.insert(to_symbol(decl_names[i]), to_func_decl(decls[i]));
|
||||
}
|
||||
for (unsigned i = 0; i < num_sorts; ++i) {
|
||||
psort* ps = ctx.pm().mk_psort_cnst(to_sort(sorts[i]));
|
||||
ctx.insert(ctx.pm().mk_psort_user_decl(0, to_symbol(sort_names[i]), ps));
|
||||
}
|
||||
if (!parse_smt2_commands(ctx, is)) {
|
||||
SET_ERROR_CODE(Z3_PARSER_ERROR);
|
||||
return of_ast(mk_c(c)->m().mk_true());
|
||||
}
|
||||
ptr_vector<expr>::const_iterator it = ctx.begin_assertions();
|
||||
ptr_vector<expr>::const_iterator end = ctx.end_assertions();
|
||||
unsigned size = static_cast<unsigned>(end - it);
|
||||
return of_ast(mk_c(c)->mk_and(size, it));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_parse_smtlib2_string(Z3_context c, Z3_string str,
|
||||
unsigned num_sorts,
|
||||
Z3_symbol const sort_names[],
|
||||
Z3_sort const sorts[],
|
||||
unsigned num_decls,
|
||||
Z3_symbol const decl_names[],
|
||||
Z3_func_decl const decls[]) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_parse_smtlib2_string(c, str, num_sorts, sort_names, sorts, num_decls, decl_names, decls);
|
||||
std::string s(str);
|
||||
std::istringstream is(s);
|
||||
Z3_ast r = parse_smtlib2_stream(false, c, is, num_sorts, sort_names, sorts, num_decls, decl_names, decls);
|
||||
RETURN_Z3(r);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_parse_smtlib2_file(Z3_context c, Z3_string file_name,
|
||||
unsigned num_sorts,
|
||||
Z3_symbol const sort_names[],
|
||||
Z3_sort const sorts[],
|
||||
unsigned num_decls,
|
||||
Z3_symbol const decl_names[],
|
||||
Z3_func_decl const decls[]) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_parse_smtlib2_string(c, file_name, num_sorts, sort_names, sorts, num_decls, decl_names, decls);
|
||||
std::ifstream is(file_name);
|
||||
if (!is) {
|
||||
SET_ERROR_CODE(Z3_PARSER_ERROR);
|
||||
return 0;
|
||||
}
|
||||
Z3_ast r = parse_smtlib2_stream(false, c, is, num_sorts, sort_names, sorts, num_decls, decl_names, decls);
|
||||
RETURN_Z3(r);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_exec_smtlib2_string(Z3_context c, Z3_string str,
|
||||
unsigned num_sorts,
|
||||
Z3_symbol sort_names[],
|
||||
Z3_sort sorts[],
|
||||
unsigned num_decls,
|
||||
Z3_symbol decl_names[],
|
||||
Z3_func_decl decls[]) {
|
||||
Z3_TRY;
|
||||
cmd_context ctx(mk_c(c)->fparams(), false, &(mk_c(c)->m()));
|
||||
std::string s(str);
|
||||
std::istringstream is(s);
|
||||
// No logging for this one, since it private.
|
||||
return parse_smtlib2_stream(true, c, is, num_sorts, sort_names, sorts, num_decls, decl_names, decls);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_exec_smtlib2_file(Z3_context c, Z3_string file_name,
|
||||
unsigned num_sorts,
|
||||
Z3_symbol sort_names[],
|
||||
Z3_sort sorts[],
|
||||
unsigned num_decls,
|
||||
Z3_symbol decl_names[],
|
||||
Z3_func_decl decls[]) {
|
||||
Z3_TRY;
|
||||
std::ifstream is(file_name);
|
||||
if (!is) {
|
||||
SET_ERROR_CODE(Z3_PARSER_ERROR);
|
||||
return 0;
|
||||
}
|
||||
// No logging for this one, since it private.
|
||||
return parse_smtlib2_stream(true, c, is, num_sorts, sort_names, sorts, num_decls, decl_names, decls);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
};
|
78
src/api/api_poly.cpp
Normal file
78
src/api/api_poly.cpp
Normal 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
40
src/api/api_poly.h
Normal 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
511
src/api/api_quant.cpp
Normal file
|
@ -0,0 +1,511 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
api_quant.cpp
|
||||
|
||||
Abstract:
|
||||
API for quantifiers
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2012-02-29.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include<iostream>
|
||||
#include"z3.h"
|
||||
#include"api_log_macros.h"
|
||||
#include"api_context.h"
|
||||
#include"api_util.h"
|
||||
#include"pattern_validation.h"
|
||||
#include"expr_abstract.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
Z3_ast Z3_API Z3_mk_quantifier(
|
||||
Z3_context c,
|
||||
Z3_bool is_forall,
|
||||
unsigned weight,
|
||||
unsigned num_patterns, Z3_pattern const patterns[],
|
||||
unsigned num_decls, Z3_sort const sorts[],
|
||||
Z3_symbol const decl_names[],
|
||||
Z3_ast body)
|
||||
{
|
||||
return Z3_mk_quantifier_ex(
|
||||
c,
|
||||
is_forall,
|
||||
weight,
|
||||
0,
|
||||
0,
|
||||
num_patterns, patterns,
|
||||
0, 0,
|
||||
num_decls, sorts,
|
||||
decl_names,
|
||||
body
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
Z3_ast mk_quantifier_ex_core(
|
||||
Z3_context c,
|
||||
Z3_bool is_forall,
|
||||
unsigned weight,
|
||||
Z3_symbol quantifier_id,
|
||||
Z3_symbol skolem_id,
|
||||
unsigned num_patterns, Z3_pattern const patterns[],
|
||||
unsigned num_no_patterns, Z3_ast const no_patterns[],
|
||||
unsigned num_decls, Z3_sort const sorts[],
|
||||
Z3_symbol const decl_names[],
|
||||
Z3_ast body) {
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
if (!mk_c(c)->m().is_bool(to_expr(body))) {
|
||||
SET_ERROR_CODE(Z3_SORT_ERROR);
|
||||
}
|
||||
if (num_patterns > 0 && num_no_patterns > 0) {
|
||||
SET_ERROR_CODE(Z3_INVALID_USAGE);
|
||||
}
|
||||
expr * const* ps = reinterpret_cast<expr * const*>(patterns);
|
||||
expr * const* no_ps = reinterpret_cast<expr * const*>(no_patterns);
|
||||
pattern_validator v(mk_c(c)->m());
|
||||
for (unsigned i = 0; i < num_patterns; i++) {
|
||||
if (!v(num_decls, ps[i])) {
|
||||
SET_ERROR_CODE(Z3_INVALID_PATTERN);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
sort* const* ts = reinterpret_cast<sort * const*>(sorts);
|
||||
svector<symbol> names;
|
||||
for (unsigned i = 0; i < num_decls; ++i) {
|
||||
names.push_back(to_symbol(decl_names[i]));
|
||||
}
|
||||
expr_ref result(mk_c(c)->m());
|
||||
if (num_decls > 0) {
|
||||
result = mk_c(c)->m().mk_quantifier(
|
||||
(0 != is_forall),
|
||||
names.size(), ts, names.c_ptr(), to_expr(body),
|
||||
weight,
|
||||
to_symbol(quantifier_id),
|
||||
to_symbol(skolem_id),
|
||||
num_patterns, ps,
|
||||
num_no_patterns, no_ps
|
||||
);
|
||||
}
|
||||
else {
|
||||
result = to_expr(body);
|
||||
}
|
||||
mk_c(c)->save_ast_trail(result.get());
|
||||
return of_ast(result.get());
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_mk_quantifier_ex(
|
||||
Z3_context c,
|
||||
Z3_bool is_forall,
|
||||
unsigned weight,
|
||||
Z3_symbol quantifier_id,
|
||||
Z3_symbol skolem_id,
|
||||
unsigned num_patterns, Z3_pattern const patterns[],
|
||||
unsigned num_no_patterns, Z3_ast const no_patterns[],
|
||||
unsigned num_decls, Z3_sort const sorts[],
|
||||
Z3_symbol const decl_names[],
|
||||
Z3_ast body)
|
||||
{
|
||||
LOG_Z3_mk_quantifier_ex(c, is_forall, weight, quantifier_id, skolem_id, num_patterns, patterns,
|
||||
num_no_patterns, no_patterns, num_decls, sorts, decl_names, body);
|
||||
Z3_ast r = mk_quantifier_ex_core(c, is_forall, weight, quantifier_id, skolem_id, num_patterns, patterns,
|
||||
num_no_patterns, no_patterns, num_decls, sorts, decl_names, body);
|
||||
RETURN_Z3(r);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_mk_forall(Z3_context c,
|
||||
unsigned weight,
|
||||
unsigned num_patterns, Z3_pattern const patterns[],
|
||||
unsigned num_decls, Z3_sort const types[],
|
||||
Z3_symbol const decl_names[],
|
||||
Z3_ast body) {
|
||||
return Z3_mk_quantifier(c, 1, weight, num_patterns, patterns, num_decls, types, decl_names, body);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_mk_exists(Z3_context c,
|
||||
unsigned weight,
|
||||
unsigned num_patterns, Z3_pattern const patterns[],
|
||||
unsigned num_decls, Z3_sort const types[],
|
||||
Z3_symbol const decl_names[],
|
||||
Z3_ast body) {
|
||||
return Z3_mk_quantifier(c, 0, weight, num_patterns, patterns, num_decls, types, decl_names, body);
|
||||
}
|
||||
|
||||
|
||||
Z3_ast Z3_API Z3_mk_quantifier_const_ex(Z3_context c,
|
||||
Z3_bool is_forall,
|
||||
unsigned weight,
|
||||
Z3_symbol quantifier_id,
|
||||
Z3_symbol skolem_id,
|
||||
unsigned num_bound,
|
||||
Z3_app const bound[],
|
||||
unsigned num_patterns,
|
||||
Z3_pattern const patterns[],
|
||||
unsigned num_no_patterns,
|
||||
Z3_ast const no_patterns[],
|
||||
Z3_ast body) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_quantifier_const_ex(c, is_forall, weight, quantifier_id, skolem_id, num_bound, bound, num_patterns, patterns,
|
||||
num_no_patterns, no_patterns, body);
|
||||
RESET_ERROR_CODE();
|
||||
svector<Z3_symbol> names;
|
||||
svector<Z3_sort> types;
|
||||
ptr_vector<expr> bound_asts;
|
||||
if (num_patterns > 0 && num_no_patterns > 0) {
|
||||
SET_ERROR_CODE(Z3_INVALID_USAGE);
|
||||
}
|
||||
for (unsigned i = 0; i < num_bound; ++i) {
|
||||
app* a = to_app(bound[i]);
|
||||
SASSERT(a->get_kind() == AST_APP);
|
||||
symbol s(to_app(a)->get_decl()->get_name());
|
||||
names.push_back(of_symbol(s));
|
||||
types.push_back(of_sort(mk_c(c)->m().get_sort(a)));
|
||||
bound_asts.push_back(a);
|
||||
if (a->get_family_id() != null_family_id || a->get_num_args() != 0) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
}
|
||||
// Abstract patterns
|
||||
svector<Z3_pattern> _patterns;
|
||||
expr_ref_vector pinned(mk_c(c)->m());
|
||||
for (unsigned i = 0; i < num_patterns; ++i) {
|
||||
expr_ref result(mk_c(c)->m());
|
||||
app* pat = to_pattern(patterns[i]);
|
||||
SASSERT(mk_c(c)->m().is_pattern(pat));
|
||||
expr_abstract(mk_c(c)->m(), 0, num_bound, bound_asts.c_ptr(), pat, result);
|
||||
SASSERT(result.get()->get_kind() == AST_APP);
|
||||
pinned.push_back(result.get());
|
||||
SASSERT(mk_c(c)->m().is_pattern(result.get()));
|
||||
_patterns.push_back(of_pattern(result.get()));
|
||||
}
|
||||
svector<Z3_ast> _no_patterns;
|
||||
for (unsigned i = 0; i < num_no_patterns; ++i) {
|
||||
expr_ref result(mk_c(c)->m());
|
||||
if (!is_app(to_expr(no_patterns[i]))) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
app* pat = to_app(to_expr(no_patterns[i]));
|
||||
expr_abstract(mk_c(c)->m(), 0, num_bound, bound_asts.c_ptr(), pat, result);
|
||||
SASSERT(result.get()->get_kind() == AST_APP);
|
||||
pinned.push_back(result.get());
|
||||
_no_patterns.push_back(of_ast(result.get()));
|
||||
}
|
||||
expr_ref abs_body(mk_c(c)->m());
|
||||
expr_abstract(mk_c(c)->m(), 0, num_bound, bound_asts.c_ptr(), to_expr(body), abs_body);
|
||||
|
||||
Z3_ast result = mk_quantifier_ex_core(c, is_forall, weight,
|
||||
quantifier_id,
|
||||
skolem_id,
|
||||
num_patterns, _patterns.c_ptr(),
|
||||
num_no_patterns, _no_patterns.c_ptr(),
|
||||
names.size(), types.c_ptr(), names.c_ptr(),
|
||||
of_ast(abs_body.get()));
|
||||
RETURN_Z3(result);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_mk_quantifier_const(Z3_context c,
|
||||
Z3_bool is_forall,
|
||||
unsigned weight,
|
||||
unsigned num_bound,
|
||||
Z3_app const bound[],
|
||||
unsigned num_patterns,
|
||||
Z3_pattern const patterns[],
|
||||
Z3_ast body) {
|
||||
return Z3_mk_quantifier_const_ex(c, is_forall, weight, 0, 0,
|
||||
num_bound, bound,
|
||||
num_patterns, patterns,
|
||||
0, 0,
|
||||
body);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_mk_forall_const(Z3_context c,
|
||||
unsigned weight,
|
||||
unsigned num_bound,
|
||||
Z3_app const bound[],
|
||||
unsigned num_patterns,
|
||||
Z3_pattern const patterns[],
|
||||
Z3_ast body) {
|
||||
return Z3_mk_quantifier_const(c, true, weight, num_bound, bound, num_patterns, patterns, body);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_mk_exists_const(Z3_context c,
|
||||
unsigned weight,
|
||||
unsigned num_bound,
|
||||
Z3_app const bound[],
|
||||
unsigned num_patterns,
|
||||
Z3_pattern const patterns[],
|
||||
Z3_ast body) {
|
||||
return Z3_mk_quantifier_const(c, false, weight, num_bound, bound, num_patterns, patterns, body);
|
||||
}
|
||||
|
||||
Z3_pattern Z3_API Z3_mk_pattern(Z3_context c, unsigned num_patterns, Z3_ast const terms[]) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_pattern(c, num_patterns, terms);
|
||||
RESET_ERROR_CODE();
|
||||
for (unsigned i = 0; i < num_patterns; ++i) {
|
||||
if (!is_app(to_expr(terms[i]))) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
}
|
||||
app* a = mk_c(c)->m().mk_pattern(num_patterns, reinterpret_cast<app*const*>(to_exprs(terms)));
|
||||
mk_c(c)->save_ast_trail(a);
|
||||
RETURN_Z3(of_pattern(a));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_mk_bound(Z3_context c, unsigned index, Z3_sort ty) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_bound(c, index, ty);
|
||||
RESET_ERROR_CODE();
|
||||
ast* a = mk_c(c)->m().mk_var(index, to_sort(ty));
|
||||
mk_c(c)->save_ast_trail(a);
|
||||
RETURN_Z3(of_ast(a));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_bool Z3_API Z3_is_quantifier_forall(Z3_context c, Z3_ast a) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_is_quantifier_forall(c, a);
|
||||
RESET_ERROR_CODE();
|
||||
ast * _a = to_ast(a);
|
||||
if (_a->get_kind() == AST_QUANTIFIER) {
|
||||
return to_quantifier(_a)->is_forall();
|
||||
}
|
||||
else {
|
||||
SET_ERROR_CODE(Z3_SORT_ERROR);
|
||||
return Z3_FALSE;
|
||||
}
|
||||
Z3_CATCH_RETURN(Z3_FALSE);
|
||||
}
|
||||
|
||||
unsigned Z3_API Z3_get_quantifier_weight(Z3_context c, Z3_ast a) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_quantifier_weight(c, a);
|
||||
RESET_ERROR_CODE();
|
||||
ast * _a = to_ast(a);
|
||||
if (_a->get_kind() == AST_QUANTIFIER) {
|
||||
return to_quantifier(_a)->get_weight();
|
||||
}
|
||||
else {
|
||||
SET_ERROR_CODE(Z3_SORT_ERROR);
|
||||
return 0;
|
||||
}
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
unsigned Z3_API Z3_get_quantifier_num_patterns(Z3_context c, Z3_ast a) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_quantifier_num_patterns(c, a);
|
||||
RESET_ERROR_CODE();
|
||||
ast * _a = to_ast(a);
|
||||
if (_a->get_kind() == AST_QUANTIFIER) {
|
||||
return to_quantifier(_a)->get_num_patterns();
|
||||
}
|
||||
else {
|
||||
SET_ERROR_CODE(Z3_SORT_ERROR);
|
||||
return 0;
|
||||
}
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_pattern Z3_API Z3_get_quantifier_pattern_ast(Z3_context c, Z3_ast a, unsigned i) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_quantifier_pattern_ast(c, a, i);
|
||||
RESET_ERROR_CODE();
|
||||
ast * _a = to_ast(a);
|
||||
if (_a->get_kind() == AST_QUANTIFIER) {
|
||||
Z3_pattern r = of_pattern(to_quantifier(_a)->get_patterns()[i]);
|
||||
RETURN_Z3(r);
|
||||
}
|
||||
else {
|
||||
SET_ERROR_CODE(Z3_SORT_ERROR);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
|
||||
unsigned Z3_API Z3_get_quantifier_num_no_patterns(Z3_context c, Z3_ast a) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_quantifier_num_no_patterns(c, a);
|
||||
RESET_ERROR_CODE();
|
||||
ast * _a = to_ast(a);
|
||||
if (_a->get_kind() == AST_QUANTIFIER) {
|
||||
return to_quantifier(_a)->get_num_no_patterns();
|
||||
}
|
||||
else {
|
||||
SET_ERROR_CODE(Z3_SORT_ERROR);
|
||||
return 0;
|
||||
}
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_get_quantifier_no_pattern_ast(Z3_context c, Z3_ast a, unsigned i) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_quantifier_no_pattern_ast(c, a, i);
|
||||
RESET_ERROR_CODE();
|
||||
ast * _a = to_ast(a);
|
||||
if (_a->get_kind() == AST_QUANTIFIER) {
|
||||
Z3_ast r = of_ast(to_quantifier(_a)->get_no_pattern(i));
|
||||
RETURN_Z3(r);
|
||||
}
|
||||
else {
|
||||
SET_ERROR_CODE(Z3_SORT_ERROR);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_symbol Z3_API Z3_get_quantifier_bound_name(Z3_context c, Z3_ast a, unsigned i) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_quantifier_bound_name(c, a, i);
|
||||
RESET_ERROR_CODE();
|
||||
ast * _a = to_ast(a);
|
||||
if (_a->get_kind() == AST_QUANTIFIER) {
|
||||
return of_symbol(to_quantifier(_a)->get_decl_names()[i]);
|
||||
}
|
||||
else {
|
||||
SET_ERROR_CODE(Z3_SORT_ERROR);
|
||||
return 0;
|
||||
}
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_sort Z3_API Z3_get_quantifier_bound_sort(Z3_context c, Z3_ast a, unsigned i) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_quantifier_bound_sort(c, a, i);
|
||||
RESET_ERROR_CODE();
|
||||
ast * _a = to_ast(a);
|
||||
if (_a->get_kind() == AST_QUANTIFIER) {
|
||||
Z3_sort r = of_sort(to_quantifier(_a)->get_decl_sort(i));
|
||||
RETURN_Z3(r);
|
||||
}
|
||||
else {
|
||||
SET_ERROR_CODE(Z3_SORT_ERROR);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_get_quantifier_body(Z3_context c, Z3_ast a) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_quantifier_body(c, a);
|
||||
RESET_ERROR_CODE();
|
||||
ast * _a = to_ast(a);
|
||||
if (_a->get_kind() == AST_QUANTIFIER) {
|
||||
Z3_ast r = of_ast(to_quantifier(_a)->get_expr());
|
||||
RETURN_Z3(r);
|
||||
}
|
||||
else {
|
||||
SET_ERROR_CODE(Z3_SORT_ERROR);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
unsigned Z3_API Z3_get_quantifier_num_bound(Z3_context c, Z3_ast a) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_quantifier_num_bound(c, a);
|
||||
RESET_ERROR_CODE();
|
||||
ast * _a = to_ast(a);
|
||||
if (_a->get_kind() == AST_QUANTIFIER) {
|
||||
|
||||
return to_quantifier(_a)->get_num_decls();
|
||||
}
|
||||
else {
|
||||
SET_ERROR_CODE(Z3_SORT_ERROR);
|
||||
return 0;
|
||||
}
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
unsigned Z3_API Z3_get_pattern_num_terms(Z3_context c, Z3_pattern p) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_pattern_num_terms(c, p);
|
||||
RESET_ERROR_CODE();
|
||||
app* _p = to_pattern(p);
|
||||
if (mk_c(c)->m().is_pattern(_p)) {
|
||||
return _p->get_num_args();
|
||||
}
|
||||
else {
|
||||
SET_ERROR_CODE(Z3_SORT_ERROR);
|
||||
return 0;
|
||||
}
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_get_pattern(Z3_context c, Z3_pattern p, unsigned idx) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_pattern(c, p, idx);
|
||||
RESET_ERROR_CODE();
|
||||
app* _p = to_pattern(p);
|
||||
if (mk_c(c)->m().is_pattern(_p)) {
|
||||
Z3_ast r = of_ast(_p->get_arg(idx));
|
||||
RETURN_Z3(r);
|
||||
}
|
||||
else {
|
||||
SET_ERROR_CODE(Z3_SORT_ERROR);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_func_decl Z3_API Z3_mk_injective_function(Z3_context c,
|
||||
Z3_symbol s,
|
||||
unsigned domain_size,
|
||||
Z3_sort const domain[],
|
||||
Z3_sort range) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_injective_function(c, s, domain_size, domain, range);
|
||||
RESET_ERROR_CODE();
|
||||
ast_manager & m = mk_c(c)->m();
|
||||
mk_c(c)->reset_last_result();
|
||||
sort* range_ = to_sort(range);
|
||||
func_decl* d = m.mk_func_decl(to_symbol(s), domain_size, to_sorts(domain), range_);
|
||||
expr_ref_vector args(m);
|
||||
expr_ref fn(m), body(m);
|
||||
vector<symbol> names;
|
||||
for (unsigned i = 0; i < domain_size; ++i) {
|
||||
unsigned idx = domain_size-i-1;
|
||||
args.push_back(m.mk_var(idx, to_sort(domain[i])));
|
||||
names.push_back(symbol(idx));
|
||||
}
|
||||
fn = m.mk_app(d, args.size(), args.c_ptr());
|
||||
|
||||
for (unsigned i = 0; i < domain_size; ++i) {
|
||||
expr* arg = args[i].get();
|
||||
sort* dom = m.get_sort(arg);
|
||||
func_decl* inv = m.mk_fresh_func_decl(symbol("inv"), to_symbol(s), 1, &range_, dom);
|
||||
body = m.mk_eq(m.mk_app(inv, fn.get()), arg);
|
||||
body = m.mk_forall(args.size(), to_sorts(domain), names.c_ptr(), body.get());
|
||||
mk_c(c)->save_multiple_ast_trail(body.get());
|
||||
mk_c(c)->assert_cnstr(body.get());
|
||||
}
|
||||
mk_c(c)->save_multiple_ast_trail(d);
|
||||
RETURN_Z3(of_func_decl(d));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_pattern_to_ast(Z3_context c, Z3_pattern p) {
|
||||
RESET_ERROR_CODE();
|
||||
return (Z3_ast)(p);
|
||||
}
|
||||
|
||||
char const * Z3_API Z3_pattern_to_string(Z3_context c, Z3_pattern p) {
|
||||
return Z3_ast_to_string(c, reinterpret_cast<Z3_ast>(p));
|
||||
}
|
||||
|
||||
};
|
322
src/api/api_solver.cpp
Normal file
322
src/api/api_solver.cpp
Normal file
|
@ -0,0 +1,322 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
api_solver.cpp
|
||||
|
||||
Abstract:
|
||||
New solver API
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2012-03-07.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include<iostream>
|
||||
#include"z3.h"
|
||||
#include"api_log_macros.h"
|
||||
#include"api_context.h"
|
||||
#include"api_tactic.h"
|
||||
#include"api_solver.h"
|
||||
#include"api_model.h"
|
||||
#include"api_stats.h"
|
||||
#include"api_ast_vector.h"
|
||||
#include"tactic2solver.h"
|
||||
#include"scoped_ctrl_c.h"
|
||||
#include"cancel_eh.h"
|
||||
#include"scoped_timer.h"
|
||||
#include"smt_strategic_solver.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
Z3_solver Z3_API Z3_mk_simple_solver(Z3_context c) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_simple_solver(c);
|
||||
RESET_ERROR_CODE();
|
||||
Z3_solver_ref * s = alloc(Z3_solver_ref);
|
||||
s->m_solver = mk_default_solver();
|
||||
s->m_solver->set_front_end_params(mk_c(c)->fparams());
|
||||
s->m_solver->init(mk_c(c)->m(), symbol::null);
|
||||
mk_c(c)->save_object(s);
|
||||
Z3_solver r = of_solver(s);
|
||||
RETURN_Z3(r);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_solver Z3_API Z3_mk_solver(Z3_context c) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_solver(c);
|
||||
RESET_ERROR_CODE();
|
||||
Z3_solver_ref * s = alloc(Z3_solver_ref);
|
||||
s->m_solver = mk_smt_strategic_solver();
|
||||
s->m_solver->set_front_end_params(mk_c(c)->fparams());
|
||||
s->m_solver->init(mk_c(c)->m(), symbol::null);
|
||||
mk_c(c)->save_object(s);
|
||||
Z3_solver r = of_solver(s);
|
||||
RETURN_Z3(r);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_solver Z3_API Z3_mk_solver_for_logic(Z3_context c, Z3_symbol logic) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_solver_for_logic(c, logic);
|
||||
RESET_ERROR_CODE();
|
||||
Z3_solver_ref * s = alloc(Z3_solver_ref);
|
||||
s->m_solver = mk_smt_strategic_solver(true /* force solver to use tactics even when auto_config is disabled */);
|
||||
s->m_solver->set_front_end_params(mk_c(c)->fparams());
|
||||
s->m_solver->init(mk_c(c)->m(), to_symbol(logic));
|
||||
mk_c(c)->save_object(s);
|
||||
Z3_solver r = of_solver(s);
|
||||
RETURN_Z3(r);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_solver Z3_API Z3_mk_solver_from_tactic(Z3_context c, Z3_tactic t) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_solver_from_tactic(c, t);
|
||||
RESET_ERROR_CODE();
|
||||
Z3_solver_ref * s = alloc(Z3_solver_ref);
|
||||
s->m_solver = alloc(tactic2solver_api, to_tactic_ref(t));
|
||||
s->m_solver->set_front_end_params(mk_c(c)->fparams());
|
||||
s->m_solver->init(mk_c(c)->m(), symbol::null);
|
||||
mk_c(c)->save_object(s);
|
||||
Z3_solver r = of_solver(s);
|
||||
RETURN_Z3(r);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_string Z3_API Z3_solver_get_help(Z3_context c, Z3_solver s) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_solver_get_help(c, s);
|
||||
RESET_ERROR_CODE();
|
||||
std::ostringstream buffer;
|
||||
param_descrs descrs;
|
||||
to_solver_ref(s)->collect_param_descrs(descrs);
|
||||
descrs.display(buffer);
|
||||
return mk_c(c)->mk_external_string(buffer.str());
|
||||
Z3_CATCH_RETURN("");
|
||||
}
|
||||
|
||||
Z3_param_descrs Z3_API Z3_solver_get_param_descrs(Z3_context c, Z3_solver s) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_solver_get_param_descrs(c, s);
|
||||
RESET_ERROR_CODE();
|
||||
Z3_param_descrs_ref * d = alloc(Z3_param_descrs_ref);
|
||||
mk_c(c)->save_object(d);
|
||||
to_solver_ref(s)->collect_param_descrs(d->m_descrs);
|
||||
Z3_param_descrs r = of_param_descrs(d);
|
||||
RETURN_Z3(r);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
void Z3_API Z3_solver_set_params(Z3_context c, Z3_solver s, Z3_params p) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_solver_set_params(c, s, p);
|
||||
RESET_ERROR_CODE();
|
||||
to_solver_ref(s)->updt_params(to_param_ref(p));
|
||||
to_solver(s)->m_params = to_param_ref(p);
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_solver_inc_ref(Z3_context c, Z3_solver s) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_solver_inc_ref(c, s);
|
||||
RESET_ERROR_CODE();
|
||||
to_solver(s)->inc_ref();
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_solver_dec_ref(Z3_context c, Z3_solver s) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_solver_dec_ref(c, s);
|
||||
RESET_ERROR_CODE();
|
||||
to_solver(s)->dec_ref();
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_solver_push(Z3_context c, Z3_solver s) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_solver_push(c, s);
|
||||
RESET_ERROR_CODE();
|
||||
to_solver_ref(s)->push();
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_solver_pop(Z3_context c, Z3_solver s, unsigned n) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_solver_pop(c, s, n);
|
||||
RESET_ERROR_CODE();
|
||||
if (n > to_solver_ref(s)->get_scope_level()) {
|
||||
SET_ERROR_CODE(Z3_IOB);
|
||||
return;
|
||||
}
|
||||
if (n > 0)
|
||||
to_solver_ref(s)->pop(n);
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_solver_reset(Z3_context c, Z3_solver s) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_solver_reset(c, s);
|
||||
RESET_ERROR_CODE();
|
||||
to_solver_ref(s)->reset();
|
||||
to_solver_ref(s)->init(mk_c(c)->m(), symbol::null);
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
unsigned Z3_API Z3_solver_get_num_scopes(Z3_context c, Z3_solver s) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_solver_get_num_scopes(c, s);
|
||||
RESET_ERROR_CODE();
|
||||
return to_solver_ref(s)->get_scope_level();
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
void Z3_API Z3_solver_assert(Z3_context c, Z3_solver s, Z3_ast a) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_solver_assert(c, s, a);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_FORMULA(a,);
|
||||
to_solver_ref(s)->assert_expr(to_expr(a));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
Z3_ast_vector Z3_API Z3_solver_get_assertions(Z3_context c, Z3_solver s) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_solver_get_assertions(c, s);
|
||||
RESET_ERROR_CODE();
|
||||
Z3_ast_vector_ref * v = alloc(Z3_ast_vector_ref, mk_c(c)->m());
|
||||
mk_c(c)->save_object(v);
|
||||
unsigned sz = to_solver_ref(s)->get_num_assertions();
|
||||
for (unsigned i = 0; i < sz; i++) {
|
||||
v->m_ast_vector.push_back(to_solver_ref(s)->get_assertion(i));
|
||||
}
|
||||
RETURN_Z3(of_ast_vector(v));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
static Z3_lbool _solver_check(Z3_context c, Z3_solver s, unsigned num_assumptions, Z3_ast const assumptions[]) {
|
||||
for (unsigned i = 0; i < num_assumptions; i++) {
|
||||
if (!is_expr(to_ast(assumptions[i]))) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
return Z3_L_UNDEF;
|
||||
}
|
||||
}
|
||||
expr * const * _assumptions = to_exprs(assumptions);
|
||||
to_solver_ref(s)->set_produce_models(to_solver(s)->m_params.get_bool(":model", true));
|
||||
to_solver_ref(s)->set_produce_proofs(mk_c(c)->m().proofs_enabled());
|
||||
to_solver_ref(s)->set_produce_unsat_cores(num_assumptions > 0);
|
||||
unsigned timeout = to_solver(s)->m_params.get_uint(":timeout", UINT_MAX);
|
||||
bool use_ctrl_c = to_solver(s)->m_params.get_bool(":ctrl-c", false);
|
||||
cancel_eh<solver> eh(*to_solver_ref(s));
|
||||
api::context::set_interruptable(*(mk_c(c)), eh);
|
||||
lbool result;
|
||||
{
|
||||
scoped_ctrl_c ctrlc(eh, false, use_ctrl_c);
|
||||
scoped_timer timer(timeout, &eh);
|
||||
try {
|
||||
result = to_solver_ref(s)->check_sat(num_assumptions, _assumptions);
|
||||
}
|
||||
catch (z3_exception & ex) {
|
||||
mk_c(c)->handle_exception(ex);
|
||||
return Z3_L_UNDEF;
|
||||
}
|
||||
}
|
||||
return static_cast<Z3_lbool>(result);
|
||||
}
|
||||
|
||||
Z3_lbool Z3_API Z3_solver_check(Z3_context c, Z3_solver s) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_solver_check(c, s);
|
||||
RESET_ERROR_CODE();
|
||||
return _solver_check(c, s, 0, 0);
|
||||
Z3_CATCH_RETURN(Z3_L_UNDEF);
|
||||
}
|
||||
|
||||
Z3_lbool Z3_API Z3_solver_check_assumptions(Z3_context c, Z3_solver s, unsigned num_assumptions, Z3_ast const assumptions[]) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_solver_check_assumptions(c, s, num_assumptions, assumptions);
|
||||
RESET_ERROR_CODE();
|
||||
return _solver_check(c, s, num_assumptions, assumptions);
|
||||
Z3_CATCH_RETURN(Z3_L_UNDEF);
|
||||
}
|
||||
|
||||
Z3_model Z3_API Z3_solver_get_model(Z3_context c, Z3_solver s) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_solver_get_model(c, s);
|
||||
RESET_ERROR_CODE();
|
||||
model_ref _m;
|
||||
to_solver_ref(s)->get_model(_m);
|
||||
if (!_m) {
|
||||
SET_ERROR_CODE(Z3_INVALID_USAGE);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
Z3_model_ref * m_ref = alloc(Z3_model_ref);
|
||||
m_ref->m_model = _m;
|
||||
mk_c(c)->save_object(m_ref);
|
||||
RETURN_Z3(of_model(m_ref));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_solver_get_proof(Z3_context c, Z3_solver s) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_solver_get_proof(c, s);
|
||||
RESET_ERROR_CODE();
|
||||
proof * p = to_solver_ref(s)->get_proof();
|
||||
if (!p) {
|
||||
SET_ERROR_CODE(Z3_INVALID_USAGE);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
mk_c(c)->save_ast_trail(p);
|
||||
RETURN_Z3(of_ast(p));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast_vector Z3_API Z3_solver_get_unsat_core(Z3_context c, Z3_solver s) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_solver_get_unsat_core(c, s);
|
||||
RESET_ERROR_CODE();
|
||||
ptr_vector<expr> core;
|
||||
to_solver_ref(s)->get_unsat_core(core);
|
||||
Z3_ast_vector_ref * v = alloc(Z3_ast_vector_ref, mk_c(c)->m());
|
||||
mk_c(c)->save_object(v);
|
||||
for (unsigned i = 0; i < core.size(); i++) {
|
||||
v->m_ast_vector.push_back(core[i]);
|
||||
}
|
||||
RETURN_Z3(of_ast_vector(v));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_string Z3_API Z3_solver_get_reason_unknown(Z3_context c, Z3_solver s) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_solver_get_reason_unknown(c, s);
|
||||
RESET_ERROR_CODE();
|
||||
return mk_c(c)->mk_external_string(to_solver_ref(s)->reason_unknown());
|
||||
Z3_CATCH_RETURN("");
|
||||
}
|
||||
|
||||
Z3_stats Z3_API Z3_solver_get_statistics(Z3_context c, Z3_solver s) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_solver_get_statistics(c, s);
|
||||
RESET_ERROR_CODE();
|
||||
Z3_stats_ref * st = alloc(Z3_stats_ref);
|
||||
to_solver_ref(s)->collect_statistics(st->m_stats);
|
||||
mk_c(c)->save_object(st);
|
||||
Z3_stats r = of_stats(st);
|
||||
RETURN_Z3(r);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_string Z3_API Z3_solver_to_string(Z3_context c, Z3_solver s) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_solver_to_string(c, s);
|
||||
RESET_ERROR_CODE();
|
||||
std::ostringstream buffer;
|
||||
to_solver_ref(s)->display(buffer);
|
||||
return mk_c(c)->mk_external_string(buffer.str());
|
||||
Z3_CATCH_RETURN("");
|
||||
}
|
||||
};
|
35
src/api/api_solver.h
Normal file
35
src/api/api_solver.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
api_solver.h
|
||||
|
||||
Abstract:
|
||||
New solver API
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2012-03-07.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _API_SOLVER_H_
|
||||
#define _API_SOLVER_H_
|
||||
|
||||
#include"api_util.h"
|
||||
#include"solver.h"
|
||||
|
||||
struct Z3_solver_ref : public api::object {
|
||||
solver * m_solver;
|
||||
params_ref m_params;
|
||||
Z3_solver_ref():m_solver(0) {}
|
||||
virtual ~Z3_solver_ref() { dealloc(m_solver); }
|
||||
};
|
||||
|
||||
inline Z3_solver_ref * to_solver(Z3_solver s) { return reinterpret_cast<Z3_solver_ref *>(s); }
|
||||
inline Z3_solver of_solver(Z3_solver_ref * s) { return reinterpret_cast<Z3_solver>(s); }
|
||||
inline solver * to_solver_ref(Z3_solver s) { return to_solver(s)->m_solver; }
|
||||
|
||||
#endif
|
365
src/api/api_solver_old.cpp
Normal file
365
src/api/api_solver_old.cpp
Normal file
|
@ -0,0 +1,365 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
api_solver_old.cpp
|
||||
|
||||
Abstract:
|
||||
OLD API for using solvers.
|
||||
|
||||
This has been deprecated
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2012-02-29.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include<iostream>
|
||||
#include"z3.h"
|
||||
#include"api_log_macros.h"
|
||||
#include"api_context.h"
|
||||
#include"api_model.h"
|
||||
#include"smt_implied_equalities.h"
|
||||
#include"cancel_eh.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
void Z3_API Z3_push(Z3_context c) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_push(c);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_SEARCHING(c);
|
||||
mk_c(c)->push();
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_pop(Z3_context c, unsigned num_scopes) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_pop(c, num_scopes);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_SEARCHING(c);
|
||||
if (num_scopes > mk_c(c)->get_solver().get_scope_level()) {
|
||||
SET_ERROR_CODE(Z3_IOB);
|
||||
return;
|
||||
}
|
||||
if (num_scopes > 0) {
|
||||
mk_c(c)->pop(num_scopes);
|
||||
}
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
unsigned Z3_API Z3_get_num_scopes(Z3_context c) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_num_scopes(c);
|
||||
RESET_ERROR_CODE();
|
||||
return mk_c(c)->get_num_scopes();
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
void Z3_API Z3_assert_cnstr(Z3_context c, Z3_ast a) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_assert_cnstr(c, a);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_FORMULA(a,);
|
||||
mk_c(c)->assert_cnstr(to_expr(a));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
Z3_lbool Z3_API Z3_check_and_get_model(Z3_context c, Z3_model * m) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_check_and_get_model(c, m);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_SEARCHING(c);
|
||||
cancel_eh<smt::solver> eh(mk_c(c)->get_solver());
|
||||
api::context::set_interruptable(*(mk_c(c)), eh);
|
||||
flet<bool> _model(mk_c(c)->fparams().m_model, true);
|
||||
lbool result;
|
||||
try {
|
||||
model_ref _m;
|
||||
result = mk_c(c)->check(_m);
|
||||
if (m) {
|
||||
if (_m) {
|
||||
Z3_model_ref * m_ref = alloc(Z3_model_ref);
|
||||
m_ref->m_model = _m;
|
||||
// Must bump reference counter for backward compatibility reasons.
|
||||
// Don't need to invoke save_object, since the counter was bumped
|
||||
m_ref->inc_ref();
|
||||
*m = of_model(m_ref);
|
||||
}
|
||||
else {
|
||||
*m = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (z3_exception & ex) {
|
||||
mk_c(c)->handle_exception(ex);
|
||||
RETURN_Z3_check_and_get_model static_cast<Z3_lbool>(l_undef);
|
||||
}
|
||||
RETURN_Z3_check_and_get_model static_cast<Z3_lbool>(result);
|
||||
Z3_CATCH_RETURN(Z3_L_UNDEF);
|
||||
}
|
||||
|
||||
Z3_lbool Z3_API Z3_check(Z3_context c) {
|
||||
Z3_TRY;
|
||||
// This is just syntax sugar...
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_SEARCHING(c);
|
||||
Z3_lbool r = Z3_check_and_get_model(c, 0);
|
||||
return r;
|
||||
Z3_CATCH_RETURN(Z3_L_UNDEF);
|
||||
}
|
||||
|
||||
Z3_lbool Z3_API Z3_get_implied_equalities(Z3_context c,
|
||||
unsigned num_terms,
|
||||
Z3_ast const terms[],
|
||||
unsigned class_ids[]) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_implied_equalities(c, num_terms, terms, class_ids);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_SEARCHING(c);
|
||||
lbool result = smt::implied_equalities(mk_c(c)->get_solver(), num_terms, to_exprs(terms), class_ids);
|
||||
return static_cast<Z3_lbool>(result);
|
||||
Z3_CATCH_RETURN(Z3_L_UNDEF);
|
||||
}
|
||||
|
||||
|
||||
Z3_lbool Z3_API Z3_check_assumptions(Z3_context c,
|
||||
unsigned num_assumptions, Z3_ast const assumptions[],
|
||||
Z3_model * m, Z3_ast* proof,
|
||||
unsigned* core_size, Z3_ast core[]) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_check_assumptions(c, num_assumptions, assumptions, m, proof, core_size, core);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_SEARCHING(c);
|
||||
expr * const* _assumptions = to_exprs(assumptions);
|
||||
flet<bool> _model(mk_c(c)->fparams().m_model, true);
|
||||
cancel_eh<smt::solver> eh(mk_c(c)->get_solver());
|
||||
api::context::set_interruptable(*(mk_c(c)), eh);
|
||||
lbool result;
|
||||
result = mk_c(c)->get_solver().check(num_assumptions, _assumptions);
|
||||
if (result != l_false && m) {
|
||||
model_ref _m;
|
||||
mk_c(c)->get_solver().get_model(_m);
|
||||
if (_m) {
|
||||
Z3_model_ref * m_ref = alloc(Z3_model_ref);
|
||||
m_ref->m_model = _m;
|
||||
// Must bump reference counter for backward compatibility reasons.
|
||||
// Don't need to invoke save_object, since the counter was bumped
|
||||
m_ref->inc_ref();
|
||||
*m = of_model(m_ref);
|
||||
}
|
||||
else {
|
||||
*m = 0;
|
||||
}
|
||||
}
|
||||
if (result == l_false && core_size) {
|
||||
*core_size = mk_c(c)->get_solver().get_unsat_core_size();
|
||||
if (*core_size > num_assumptions) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
}
|
||||
for (unsigned i = 0; i < *core_size; ++i) {
|
||||
core[i] = of_ast(mk_c(c)->get_solver().get_unsat_core_expr(i));
|
||||
}
|
||||
}
|
||||
else if (core_size) {
|
||||
*core_size = 0;
|
||||
}
|
||||
if (result == l_false && proof) {
|
||||
*proof = of_ast(mk_c(c)->get_solver().get_proof());
|
||||
}
|
||||
else if (proof) {
|
||||
*proof = 0; // breaks abstraction.
|
||||
}
|
||||
RETURN_Z3_check_assumptions static_cast<Z3_lbool>(result);
|
||||
Z3_CATCH_RETURN(Z3_L_UNDEF);
|
||||
}
|
||||
|
||||
Z3_search_failure Z3_API Z3_get_search_failure(Z3_context c) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_search_failure(c);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_SEARCHING(c);
|
||||
smt::failure f = mk_c(c)->get_solver().last_failure();
|
||||
return api::mk_Z3_search_failure(f);
|
||||
Z3_CATCH_RETURN(Z3_UNKNOWN);
|
||||
}
|
||||
|
||||
class labeled_literal {
|
||||
expr_ref m_literal;
|
||||
symbol m_label;
|
||||
bool m_enabled;
|
||||
public:
|
||||
labeled_literal(ast_manager& m, expr* l, symbol const& n) : m_literal(l,m), m_label(n), m_enabled(true) {}
|
||||
labeled_literal(ast_manager& m, expr* l) : m_literal(l,m), m_label(), m_enabled(true) {}
|
||||
bool is_enabled() const { return m_enabled; }
|
||||
void disable() { m_enabled = false; }
|
||||
symbol const& get_label() const { return m_label; }
|
||||
expr* get_literal() { return m_literal.get(); }
|
||||
};
|
||||
|
||||
typedef vector<labeled_literal> labels;
|
||||
|
||||
Z3_literals Z3_API Z3_get_relevant_labels(Z3_context c) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_relevant_labels(c);
|
||||
RESET_ERROR_CODE();
|
||||
buffer<symbol> labl_syms;
|
||||
ast_manager& m = mk_c(c)->m();
|
||||
expr_ref_vector lits(m);
|
||||
mk_c(c)->get_solver().get_relevant_labels(0, labl_syms);
|
||||
mk_c(c)->get_solver().get_relevant_labeled_literals(mk_c(c)->fparams().m_at_labels_cex, lits);
|
||||
labels* lbls = alloc(labels);
|
||||
SASSERT(labl_syms.size() == lits.size());
|
||||
for (unsigned i = 0; i < lits.size(); ++i) {
|
||||
lbls->push_back(labeled_literal(m,lits[i].get(), labl_syms[i]));
|
||||
}
|
||||
RETURN_Z3(reinterpret_cast<Z3_literals>(lbls));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_literals Z3_API Z3_get_relevant_literals(Z3_context c) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_relevant_literals(c);
|
||||
RESET_ERROR_CODE();
|
||||
ast_manager& m = mk_c(c)->m();
|
||||
expr_ref_vector lits(m);
|
||||
mk_c(c)->get_solver().get_relevant_literals(lits);
|
||||
labels* lbls = alloc(labels);
|
||||
for (unsigned i = 0; i < lits.size(); ++i) {
|
||||
lbls->push_back(labeled_literal(m,lits[i].get()));
|
||||
}
|
||||
RETURN_Z3(reinterpret_cast<Z3_literals>(lbls));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_literals Z3_API Z3_get_guessed_literals(Z3_context c) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_guessed_literals(c);
|
||||
RESET_ERROR_CODE();
|
||||
ast_manager& m = mk_c(c)->m();
|
||||
expr_ref_vector lits(m);
|
||||
mk_c(c)->get_solver().get_guessed_literals(lits);
|
||||
labels* lbls = alloc(labels);
|
||||
for (unsigned i = 0; i < lits.size(); ++i) {
|
||||
lbls->push_back(labeled_literal(m,lits[i].get()));
|
||||
}
|
||||
RETURN_Z3(reinterpret_cast<Z3_literals>(lbls));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
void Z3_API Z3_del_literals(Z3_context c, Z3_literals lbls) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_del_literals(c, lbls);
|
||||
RESET_ERROR_CODE();
|
||||
dealloc(reinterpret_cast<labels*>(lbls));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
unsigned Z3_API Z3_get_num_literals(Z3_context c,Z3_literals lbls) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_num_literals(c, lbls);
|
||||
RESET_ERROR_CODE();
|
||||
return reinterpret_cast<labels*>(lbls)->size();
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_symbol Z3_API Z3_get_label_symbol(Z3_context c,Z3_literals lbls, unsigned idx) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_label_symbol(c, lbls, idx);
|
||||
RESET_ERROR_CODE();
|
||||
return of_symbol((*reinterpret_cast<labels*>(lbls))[idx].get_label());
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_get_literal(Z3_context c,Z3_literals lbls, unsigned idx) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_literal(c, lbls, idx);
|
||||
RESET_ERROR_CODE();
|
||||
expr* e = (*reinterpret_cast<labels*>(lbls))[idx].get_literal();
|
||||
mk_c(c)->save_ast_trail(e);
|
||||
RETURN_Z3(of_ast(e));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
void Z3_API Z3_disable_literal(Z3_context c, Z3_literals lbls, unsigned idx) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_disable_literal(c, lbls, idx);
|
||||
RESET_ERROR_CODE();
|
||||
(*reinterpret_cast<labels*>(lbls))[idx].disable();
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_block_literals(Z3_context c, Z3_literals lbls) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_block_literals(c, lbls);
|
||||
RESET_ERROR_CODE();
|
||||
labels* _lbls = reinterpret_cast<labels*>(lbls);
|
||||
ast_manager& m = mk_c(c)->m();
|
||||
expr_ref_vector lits(m);
|
||||
for (unsigned i = 0; i < _lbls->size(); ++i) {
|
||||
if ((*_lbls)[i].is_enabled()) {
|
||||
lits.push_back(m.mk_not((*_lbls)[i].get_literal()));
|
||||
}
|
||||
}
|
||||
expr_ref clause(m);
|
||||
clause = m.mk_or(lits.size(), lits.c_ptr());
|
||||
mk_c(c)->save_ast_trail(clause.get());
|
||||
mk_c(c)->assert_cnstr(clause.get());
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
char const * Z3_API Z3_context_to_string(Z3_context c) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_context_to_string(c);
|
||||
RESET_ERROR_CODE();
|
||||
std::ostringstream buffer;
|
||||
mk_c(c)->get_solver().display(buffer);
|
||||
return mk_c(c)->mk_external_string(buffer.str());
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_get_context_assignment(Z3_context c) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_context_assignment(c);
|
||||
RESET_ERROR_CODE();
|
||||
ast_manager& m = mk_c(c)->m();
|
||||
expr_ref result(m);
|
||||
expr_ref_vector assignment(m);
|
||||
mk_c(c)->get_solver().get_assignments(assignment);
|
||||
result = mk_c(c)->mk_and(assignment.size(), assignment.c_ptr());
|
||||
RETURN_Z3(of_ast(result.get()));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_string Z3_API Z3_statistics_to_string(Z3_context c) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_statistics_to_string(c);
|
||||
RESET_ERROR_CODE();
|
||||
std::ostringstream buffer;
|
||||
mk_c(c)->get_solver().display_statistics(buffer);
|
||||
memory::display_max_usage(buffer);
|
||||
return mk_c(c)->mk_external_string(buffer.str());
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
void Z3_API Z3_soft_check_cancel(Z3_context c) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_soft_check_cancel(c);
|
||||
RESET_ERROR_CODE();
|
||||
mk_c(c)->interrupt();
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
void Z3_display_statistics(Z3_context c, std::ostream& s) {
|
||||
mk_c(c)->get_solver().display_statistics(s);
|
||||
}
|
||||
|
||||
void Z3_display_istatistics(Z3_context c, std::ostream& s) {
|
||||
mk_c(c)->get_solver().display_istatistics(s);
|
||||
}
|
||||
|
133
src/api/api_stats.cpp
Normal file
133
src/api/api_stats.cpp
Normal file
|
@ -0,0 +1,133 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
api_stats.cpp
|
||||
|
||||
Abstract:
|
||||
API for browsing statistics
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2012-03-07.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include<iostream>
|
||||
#include"z3.h"
|
||||
#include"api_log_macros.h"
|
||||
#include"api_context.h"
|
||||
#include"api_stats.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
Z3_string Z3_API Z3_stats_to_string(Z3_context c, Z3_stats s) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_stats_to_string(c, s);
|
||||
RESET_ERROR_CODE();
|
||||
std::ostringstream buffer;
|
||||
to_stats_ref(s).display_smt2(buffer);
|
||||
std::string result = buffer.str();
|
||||
// Hack for removing the trailing '\n'
|
||||
result = buffer.str();
|
||||
SASSERT(result.size() > 0);
|
||||
result.resize(result.size()-1);
|
||||
return mk_c(c)->mk_external_string(result);
|
||||
Z3_CATCH_RETURN("");
|
||||
}
|
||||
|
||||
void Z3_API Z3_stats_inc_ref(Z3_context c, Z3_stats s) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_stats_inc_ref(c, s);
|
||||
RESET_ERROR_CODE();
|
||||
to_stats(s)->inc_ref();
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_stats_dec_ref(Z3_context c, Z3_stats s) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_stats_dec_ref(c, s);
|
||||
RESET_ERROR_CODE();
|
||||
to_stats(s)->dec_ref();
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
unsigned Z3_API Z3_stats_size(Z3_context c, Z3_stats s) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_stats_size(c, s);
|
||||
RESET_ERROR_CODE();
|
||||
return to_stats_ref(s).size();
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_string Z3_API Z3_stats_get_key(Z3_context c, Z3_stats s, unsigned idx) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_stats_get_key(c, s, idx);
|
||||
RESET_ERROR_CODE();
|
||||
if (idx >= to_stats_ref(s).size()) {
|
||||
SET_ERROR_CODE(Z3_IOB);
|
||||
return "";
|
||||
}
|
||||
return to_stats_ref(s).get_key(idx);
|
||||
Z3_CATCH_RETURN("");
|
||||
}
|
||||
|
||||
Z3_bool Z3_API Z3_stats_is_uint(Z3_context c, Z3_stats s, unsigned idx) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_stats_is_uint(c, s, idx);
|
||||
RESET_ERROR_CODE();
|
||||
if (idx >= to_stats_ref(s).size()) {
|
||||
SET_ERROR_CODE(Z3_IOB);
|
||||
return Z3_FALSE;
|
||||
}
|
||||
return to_stats_ref(s).is_uint(idx);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_bool Z3_API Z3_stats_is_double(Z3_context c, Z3_stats s, unsigned idx) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_stats_is_double(c, s, idx);
|
||||
RESET_ERROR_CODE();
|
||||
if (idx >= to_stats_ref(s).size()) {
|
||||
SET_ERROR_CODE(Z3_IOB);
|
||||
return Z3_FALSE;
|
||||
}
|
||||
return !to_stats_ref(s).is_uint(idx);
|
||||
Z3_CATCH_RETURN(Z3_FALSE);
|
||||
}
|
||||
|
||||
unsigned Z3_API Z3_stats_get_uint_value(Z3_context c, Z3_stats s, unsigned idx) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_stats_get_uint_value(c, s, idx);
|
||||
RESET_ERROR_CODE();
|
||||
if (idx >= to_stats_ref(s).size()) {
|
||||
SET_ERROR_CODE(Z3_IOB);
|
||||
return 0;
|
||||
}
|
||||
if (!to_stats_ref(s).is_uint(idx)) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
return 0;
|
||||
}
|
||||
return to_stats_ref(s).get_uint_value(idx);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
double Z3_API Z3_stats_get_double_value(Z3_context c, Z3_stats s, unsigned idx) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_stats_get_double_value(c, s, idx);
|
||||
RESET_ERROR_CODE();
|
||||
if (idx >= to_stats_ref(s).size()) {
|
||||
SET_ERROR_CODE(Z3_IOB);
|
||||
return 0.0;
|
||||
}
|
||||
if (to_stats_ref(s).is_uint(idx)) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
return 0.0;
|
||||
}
|
||||
return to_stats_ref(s).get_double_value(idx);
|
||||
Z3_CATCH_RETURN(0.0);
|
||||
}
|
||||
|
||||
};
|
33
src/api/api_stats.h
Normal file
33
src/api/api_stats.h
Normal file
|
@ -0,0 +1,33 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
api_stats.h
|
||||
|
||||
Abstract:
|
||||
API for Z3 statistics
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2012-03-07.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _API_STATS_H_
|
||||
#define _API_STATS_H_
|
||||
|
||||
#include"api_util.h"
|
||||
#include"statistics.h"
|
||||
|
||||
struct Z3_stats_ref : public api::object {
|
||||
statistics m_stats;
|
||||
virtual ~Z3_stats_ref() {}
|
||||
};
|
||||
|
||||
inline Z3_stats_ref * to_stats(Z3_stats s) { return reinterpret_cast<Z3_stats_ref *>(s); }
|
||||
inline Z3_stats of_stats(Z3_stats_ref * s) { return reinterpret_cast<Z3_stats>(s); }
|
||||
inline statistics & to_stats_ref(Z3_stats s) { return to_stats(s)->m_stats; }
|
||||
|
||||
#endif
|
528
src/api/api_tactic.cpp
Normal file
528
src/api/api_tactic.cpp
Normal file
|
@ -0,0 +1,528 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
api_tactic.cpp
|
||||
|
||||
Abstract:
|
||||
API for creating tactics and probes
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2012-03-06.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include<iostream>
|
||||
#include"z3.h"
|
||||
#include"api_log_macros.h"
|
||||
#include"api_context.h"
|
||||
#include"api_tactic.h"
|
||||
#include"api_model.h"
|
||||
#include"scoped_ctrl_c.h"
|
||||
#include"cancel_eh.h"
|
||||
#include"scoped_timer.h"
|
||||
|
||||
Z3_apply_result_ref::Z3_apply_result_ref(ast_manager & m):m_core(m) {
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
#define RETURN_TACTIC(_t_) { \
|
||||
Z3_tactic_ref * _ref_ = alloc(Z3_tactic_ref); \
|
||||
_ref_->m_tactic = _t_; \
|
||||
mk_c(c)->save_object(_ref_); \
|
||||
Z3_tactic _result_ = of_tactic(_ref_); \
|
||||
RETURN_Z3(_result_); \
|
||||
}
|
||||
|
||||
#define RETURN_PROBE(_t_) { \
|
||||
Z3_probe_ref * _ref_ = alloc(Z3_probe_ref); \
|
||||
_ref_->m_probe = _t_; \
|
||||
mk_c(c)->save_object(_ref_); \
|
||||
Z3_probe _result_ = of_probe(_ref_); \
|
||||
RETURN_Z3(_result_); \
|
||||
}
|
||||
|
||||
Z3_tactic Z3_API Z3_mk_tactic(Z3_context c, Z3_string name) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_tactic(c, name);
|
||||
RESET_ERROR_CODE();
|
||||
tactic_cmd * t = mk_c(c)->find_tactic_cmd(symbol(name));
|
||||
if (t == 0) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
tactic * new_t = t->mk(mk_c(c)->m());
|
||||
RETURN_TACTIC(new_t);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
void Z3_API Z3_tactic_inc_ref(Z3_context c, Z3_tactic t) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_tactic_inc_ref(c, t);
|
||||
RESET_ERROR_CODE();
|
||||
to_tactic(t)->inc_ref();
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_tactic_dec_ref(Z3_context c, Z3_tactic t) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_tactic_dec_ref(c, t);
|
||||
RESET_ERROR_CODE();
|
||||
to_tactic(t)->dec_ref();
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
Z3_probe Z3_API Z3_mk_probe(Z3_context c, Z3_string name) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_probe(c, name);
|
||||
RESET_ERROR_CODE();
|
||||
probe_info * p = mk_c(c)->find_probe(symbol(name));
|
||||
if (p == 0) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
probe * new_p = p->get();
|
||||
RETURN_PROBE(new_p);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
void Z3_API Z3_probe_inc_ref(Z3_context c, Z3_probe p) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_probe_inc_ref(c, p);
|
||||
RESET_ERROR_CODE();
|
||||
to_probe(p)->inc_ref();
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_probe_dec_ref(Z3_context c, Z3_probe p) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_probe_dec_ref(c, p);
|
||||
RESET_ERROR_CODE();
|
||||
to_probe(p)->dec_ref();
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
Z3_tactic Z3_API Z3_tactic_and_then(Z3_context c, Z3_tactic t1, Z3_tactic t2) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_tactic_and_then(c, t1, t2);
|
||||
RESET_ERROR_CODE();
|
||||
tactic * new_t = and_then(to_tactic_ref(t1), to_tactic_ref(t2));
|
||||
RETURN_TACTIC(new_t);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_tactic Z3_API Z3_tactic_or_else(Z3_context c, Z3_tactic t1, Z3_tactic t2) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_tactic_or_else(c, t1, t2);
|
||||
RESET_ERROR_CODE();
|
||||
tactic * new_t = or_else(to_tactic_ref(t1), to_tactic_ref(t2));
|
||||
RETURN_TACTIC(new_t);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_tactic Z3_API Z3_tactic_par_or(Z3_context c, unsigned num, Z3_tactic const ts[]) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_tactic_par_or(c, num, ts);
|
||||
RESET_ERROR_CODE();
|
||||
ptr_buffer<tactic> _ts;
|
||||
for (unsigned i = 0; i < num; i++) {
|
||||
_ts.push_back(to_tactic_ref(ts[i]));
|
||||
}
|
||||
tactic * new_t = par(num, _ts.c_ptr());
|
||||
RETURN_TACTIC(new_t);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_tactic Z3_API Z3_tactic_par_and_then(Z3_context c, Z3_tactic t1, Z3_tactic t2) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_tactic_par_and_then(c, t1, t2);
|
||||
RESET_ERROR_CODE();
|
||||
tactic * new_t = par_and_then(to_tactic_ref(t1), to_tactic_ref(t2));
|
||||
RETURN_TACTIC(new_t);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_tactic Z3_API Z3_tactic_try_for(Z3_context c, Z3_tactic t, unsigned ms) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_tactic_try_for(c, t, ms);
|
||||
RESET_ERROR_CODE();
|
||||
tactic * new_t = try_for(to_tactic_ref(t), ms);
|
||||
RETURN_TACTIC(new_t);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_tactic Z3_API Z3_tactic_when(Z3_context c, Z3_probe p, Z3_tactic t) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_tactic_when(c, p, t);
|
||||
RESET_ERROR_CODE();
|
||||
tactic * new_t = when(to_probe_ref(p), to_tactic_ref(t));
|
||||
RETURN_TACTIC(new_t);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_tactic Z3_API Z3_tactic_cond(Z3_context c, Z3_probe p, Z3_tactic t1, Z3_tactic t2) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_tactic_cond(c, p, t1, t2);
|
||||
RESET_ERROR_CODE();
|
||||
tactic * new_t = cond(to_probe_ref(p), to_tactic_ref(t1), to_tactic_ref(t2));
|
||||
RETURN_TACTIC(new_t);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_tactic Z3_API Z3_tactic_repeat(Z3_context c, Z3_tactic t, unsigned max) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_tactic_repeat(c, t, max);
|
||||
RESET_ERROR_CODE();
|
||||
tactic * new_t = repeat(to_tactic_ref(t), max);
|
||||
RETURN_TACTIC(new_t);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_tactic Z3_API Z3_tactic_skip(Z3_context c) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_tactic_skip(c);
|
||||
RESET_ERROR_CODE();
|
||||
tactic * new_t = mk_skip_tactic();
|
||||
RETURN_TACTIC(new_t);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_tactic Z3_API Z3_tactic_fail(Z3_context c) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_tactic_fail(c);
|
||||
RESET_ERROR_CODE();
|
||||
tactic * new_t = mk_fail_tactic();
|
||||
RETURN_TACTIC(new_t);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_tactic Z3_API Z3_tactic_fail_if(Z3_context c, Z3_probe p) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_tactic_fail_if(c, p);
|
||||
RESET_ERROR_CODE();
|
||||
tactic * new_t = fail_if(to_probe_ref(p));
|
||||
RETURN_TACTIC(new_t);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_tactic Z3_API Z3_tactic_fail_if_not_decided(Z3_context c) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_tactic_fail_if_not_decided(c);
|
||||
RESET_ERROR_CODE();
|
||||
tactic * new_t = mk_fail_if_undecided_tactic();
|
||||
RETURN_TACTIC(new_t);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_tactic Z3_API Z3_tactic_using_params(Z3_context c, Z3_tactic t, Z3_params p) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_tactic_using_params(c, t, p);
|
||||
RESET_ERROR_CODE();
|
||||
tactic * new_t = using_params(to_tactic_ref(t), to_param_ref(p));
|
||||
RETURN_TACTIC(new_t);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_probe Z3_API Z3_probe_const(Z3_context c, double val) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_probe_const(c, val);
|
||||
RESET_ERROR_CODE();
|
||||
probe * new_p = mk_const_probe(val);
|
||||
RETURN_PROBE(new_p);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_probe Z3_API Z3_probe_lt(Z3_context c, Z3_probe p1, Z3_probe p2) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_probe_lt(c, p1, p2);
|
||||
RESET_ERROR_CODE();
|
||||
probe * new_p = mk_lt(to_probe_ref(p1), to_probe_ref(p2));
|
||||
RETURN_PROBE(new_p);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_probe Z3_API Z3_probe_gt(Z3_context c, Z3_probe p1, Z3_probe p2) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_probe_gt(c, p1, p2);
|
||||
RESET_ERROR_CODE();
|
||||
probe * new_p = mk_gt(to_probe_ref(p1), to_probe_ref(p2));
|
||||
RETURN_PROBE(new_p);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_probe Z3_API Z3_probe_le(Z3_context c, Z3_probe p1, Z3_probe p2) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_probe_le(c, p1, p2);
|
||||
RESET_ERROR_CODE();
|
||||
probe * new_p = mk_le(to_probe_ref(p1), to_probe_ref(p2));
|
||||
RETURN_PROBE(new_p);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_probe Z3_API Z3_probe_ge(Z3_context c, Z3_probe p1, Z3_probe p2) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_probe_ge(c, p1, p2);
|
||||
RESET_ERROR_CODE();
|
||||
probe * new_p = mk_ge(to_probe_ref(p1), to_probe_ref(p2));
|
||||
RETURN_PROBE(new_p);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_probe Z3_API Z3_probe_eq(Z3_context c, Z3_probe p1, Z3_probe p2) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_probe_eq(c, p1, p2);
|
||||
RESET_ERROR_CODE();
|
||||
probe * new_p = mk_eq(to_probe_ref(p1), to_probe_ref(p2));
|
||||
RETURN_PROBE(new_p);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_probe Z3_API Z3_probe_and(Z3_context c, Z3_probe p1, Z3_probe p2) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_probe_and(c, p1, p2);
|
||||
RESET_ERROR_CODE();
|
||||
probe * new_p = mk_and(to_probe_ref(p1), to_probe_ref(p2));
|
||||
RETURN_PROBE(new_p);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_probe Z3_API Z3_probe_or(Z3_context c, Z3_probe p1, Z3_probe p2) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_probe_or(c, p1, p2);
|
||||
RESET_ERROR_CODE();
|
||||
probe * new_p = mk_or(to_probe_ref(p1), to_probe_ref(p2));
|
||||
RETURN_PROBE(new_p);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_probe Z3_API Z3_probe_not(Z3_context c, Z3_probe p) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_probe_not(c, p);
|
||||
RESET_ERROR_CODE();
|
||||
probe * new_p = mk_not(to_probe_ref(p));
|
||||
RETURN_PROBE(new_p);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
unsigned Z3_API Z3_get_num_tactics(Z3_context c) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_num_tactics(c);
|
||||
RESET_ERROR_CODE();
|
||||
return mk_c(c)->num_tactics();
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_string Z3_API Z3_get_tactic_name(Z3_context c, unsigned idx) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_tactic_name(c, idx);
|
||||
RESET_ERROR_CODE();
|
||||
if (idx >= mk_c(c)->num_tactics()) {
|
||||
SET_ERROR_CODE(Z3_IOB);
|
||||
return "";
|
||||
}
|
||||
return mk_c(c)->get_tactic(idx)->get_name().bare_str();
|
||||
Z3_CATCH_RETURN("");
|
||||
}
|
||||
|
||||
unsigned Z3_API Z3_get_num_probes(Z3_context c) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_num_probes(c);
|
||||
RESET_ERROR_CODE();
|
||||
return mk_c(c)->num_probes();
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_string Z3_API Z3_get_probe_name(Z3_context c, unsigned idx) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_probe_name(c, idx);
|
||||
RESET_ERROR_CODE();
|
||||
if (idx >= mk_c(c)->num_probes()) {
|
||||
SET_ERROR_CODE(Z3_IOB);
|
||||
return "";
|
||||
}
|
||||
return mk_c(c)->get_probe(idx)->get_name().bare_str();
|
||||
Z3_CATCH_RETURN("");
|
||||
}
|
||||
|
||||
Z3_string Z3_API Z3_tactic_get_help(Z3_context c, Z3_tactic t) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_tactic_get_help(c, t);
|
||||
RESET_ERROR_CODE();
|
||||
std::ostringstream buffer;
|
||||
param_descrs descrs;
|
||||
to_tactic_ref(t)->collect_param_descrs(descrs);
|
||||
descrs.display(buffer);
|
||||
return mk_c(c)->mk_external_string(buffer.str());
|
||||
Z3_CATCH_RETURN("");
|
||||
}
|
||||
|
||||
Z3_param_descrs Z3_API Z3_tactic_get_param_descrs(Z3_context c, Z3_tactic t) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_tactic_get_param_descrs(c, t);
|
||||
RESET_ERROR_CODE();
|
||||
Z3_param_descrs_ref * d = alloc(Z3_param_descrs_ref);
|
||||
mk_c(c)->save_object(d);
|
||||
to_tactic_ref(t)->collect_param_descrs(d->m_descrs);
|
||||
Z3_param_descrs r = of_param_descrs(d);
|
||||
RETURN_Z3(r);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_string Z3_API Z3_tactic_get_descr(Z3_context c, Z3_string name) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_tactic_get_descr(c, name);
|
||||
RESET_ERROR_CODE();
|
||||
tactic_cmd * t = mk_c(c)->find_tactic_cmd(symbol(name));
|
||||
if (t == 0) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
return "";
|
||||
}
|
||||
return t->get_descr();
|
||||
Z3_CATCH_RETURN("");
|
||||
}
|
||||
|
||||
Z3_string Z3_API Z3_probe_get_descr(Z3_context c, Z3_string name) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_probe_get_descr(c, name);
|
||||
RESET_ERROR_CODE();
|
||||
probe_info * p = mk_c(c)->find_probe(symbol(name));
|
||||
if (p == 0) {
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
return "";
|
||||
}
|
||||
return p->get_descr();
|
||||
Z3_CATCH_RETURN("");
|
||||
}
|
||||
|
||||
static Z3_apply_result _tactic_apply(Z3_context c, Z3_tactic t, Z3_goal g, params_ref p) {
|
||||
goal_ref new_goal;
|
||||
new_goal = alloc(goal, *to_goal_ref(g));
|
||||
Z3_apply_result_ref * ref = alloc(Z3_apply_result_ref, mk_c(c)->m());
|
||||
mk_c(c)->save_object(ref);
|
||||
|
||||
unsigned timeout = p.get_uint(":timeout", UINT_MAX);
|
||||
bool use_ctrl_c = p.get_bool(":ctrl-c", false);
|
||||
cancel_eh<tactic> eh(*to_tactic_ref(t));
|
||||
|
||||
to_tactic_ref(t)->updt_params(p);
|
||||
|
||||
api::context::set_interruptable(*(mk_c(c)), eh);
|
||||
{
|
||||
scoped_ctrl_c ctrlc(eh, false, use_ctrl_c);
|
||||
scoped_timer timer(timeout, &eh);
|
||||
try {
|
||||
exec(*to_tactic_ref(t), new_goal, ref->m_subgoals, ref->m_mc, ref->m_pc, ref->m_core);
|
||||
return of_apply_result(ref);
|
||||
}
|
||||
catch (z3_exception & ex) {
|
||||
mk_c(c)->handle_exception(ex);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
double Z3_API Z3_probe_apply(Z3_context c, Z3_probe p, Z3_goal g) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_probe_apply(c, p, g);
|
||||
RESET_ERROR_CODE();
|
||||
return to_probe_ref(p)->operator()(*to_goal_ref(g)).get_value();
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_apply_result Z3_API Z3_tactic_apply(Z3_context c, Z3_tactic t, Z3_goal g) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_tactic_apply(c, t, g);
|
||||
RESET_ERROR_CODE();
|
||||
params_ref p;
|
||||
Z3_apply_result r = _tactic_apply(c, t, g, p);
|
||||
RETURN_Z3(r);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_apply_result Z3_API Z3_tactic_apply_ex(Z3_context c, Z3_tactic t, Z3_goal g, Z3_params p) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_tactic_apply_ex(c, t, g, p);
|
||||
RESET_ERROR_CODE();
|
||||
Z3_apply_result r = _tactic_apply(c, t, g, to_param_ref(p));
|
||||
RETURN_Z3(r);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
void Z3_API Z3_apply_result_inc_ref(Z3_context c, Z3_apply_result r) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_apply_result_inc_ref(c, r);
|
||||
RESET_ERROR_CODE();
|
||||
to_apply_result(r)->inc_ref();
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_apply_result_dec_ref(Z3_context c, Z3_apply_result r) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_apply_result_dec_ref(c, r);
|
||||
RESET_ERROR_CODE();
|
||||
to_apply_result(r)->dec_ref();
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
Z3_string Z3_API Z3_apply_result_to_string(Z3_context c, Z3_apply_result r) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_apply_result_to_string(c, r);
|
||||
RESET_ERROR_CODE();
|
||||
std::ostringstream buffer;
|
||||
buffer << "(goals\n";
|
||||
unsigned sz = to_apply_result(r)->m_subgoals.size();
|
||||
for (unsigned i = 0; i < sz; i++) {
|
||||
to_apply_result(r)->m_subgoals[i]->display(buffer);
|
||||
}
|
||||
buffer << ")";
|
||||
return mk_c(c)->mk_external_string(buffer.str());
|
||||
Z3_CATCH_RETURN("");
|
||||
}
|
||||
|
||||
unsigned Z3_API Z3_apply_result_get_num_subgoals(Z3_context c, Z3_apply_result r) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_apply_result_get_num_subgoals(c, r);
|
||||
RESET_ERROR_CODE();
|
||||
return to_apply_result(r)->m_subgoals.size();
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_goal Z3_API Z3_apply_result_get_subgoal(Z3_context c, Z3_apply_result r, unsigned i) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_apply_result_get_subgoal(c, r, i);
|
||||
RESET_ERROR_CODE();
|
||||
if (i > to_apply_result(r)->m_subgoals.size()) {
|
||||
SET_ERROR_CODE(Z3_IOB);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
Z3_goal_ref * g = alloc(Z3_goal_ref);
|
||||
g->m_goal = to_apply_result(r)->m_subgoals[i];
|
||||
mk_c(c)->save_object(g);
|
||||
Z3_goal result = of_goal(g);
|
||||
RETURN_Z3(result);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_model Z3_API Z3_apply_result_convert_model(Z3_context c, Z3_apply_result r, unsigned i, Z3_model m) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_apply_result_convert_model(c, r, i, m);
|
||||
RESET_ERROR_CODE();
|
||||
if (i > to_apply_result(r)->m_subgoals.size()) {
|
||||
SET_ERROR_CODE(Z3_IOB);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
model_ref new_m = to_model_ref(m)->copy();
|
||||
if (to_apply_result(r)->m_mc)
|
||||
to_apply_result(r)->m_mc->operator()(new_m, i);
|
||||
Z3_model_ref * m_ref = alloc(Z3_model_ref);
|
||||
m_ref->m_model = new_m;
|
||||
mk_c(c)->save_object(m_ref);
|
||||
RETURN_Z3(of_model(m_ref));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
};
|
54
src/api/api_tactic.h
Normal file
54
src/api/api_tactic.h
Normal file
|
@ -0,0 +1,54 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
api_tactic.h
|
||||
|
||||
Abstract:
|
||||
API for creating tactics and goals.
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2012-03-06.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _API_TACTIC_H_
|
||||
#define _API_TACTIC_H_
|
||||
|
||||
#include"api_goal.h"
|
||||
#include"tactical.h"
|
||||
|
||||
struct Z3_tactic_ref : public api::object {
|
||||
tactic_ref m_tactic;
|
||||
virtual ~Z3_tactic_ref() {}
|
||||
};
|
||||
|
||||
struct Z3_probe_ref : public api::object {
|
||||
probe_ref m_probe;
|
||||
virtual ~Z3_probe_ref() {}
|
||||
};
|
||||
|
||||
inline Z3_tactic_ref * to_tactic(Z3_tactic g) { return reinterpret_cast<Z3_tactic_ref *>(g); }
|
||||
inline Z3_tactic of_tactic(Z3_tactic_ref * g) { return reinterpret_cast<Z3_tactic>(g); }
|
||||
inline tactic * to_tactic_ref(Z3_tactic g) { return g == 0 ? 0 : to_tactic(g)->m_tactic.get(); }
|
||||
|
||||
inline Z3_probe_ref * to_probe(Z3_probe g) { return reinterpret_cast<Z3_probe_ref *>(g); }
|
||||
inline Z3_probe of_probe(Z3_probe_ref * g) { return reinterpret_cast<Z3_probe>(g); }
|
||||
inline probe * to_probe_ref(Z3_probe g) { return g == 0 ? 0 : to_probe(g)->m_probe.get(); }
|
||||
|
||||
struct Z3_apply_result_ref : public api::object {
|
||||
goal_ref_buffer m_subgoals;
|
||||
model_converter_ref m_mc;
|
||||
proof_converter_ref m_pc;
|
||||
expr_dependency_ref m_core;
|
||||
Z3_apply_result_ref(ast_manager & m);
|
||||
virtual ~Z3_apply_result_ref() {}
|
||||
};
|
||||
|
||||
inline Z3_apply_result_ref * to_apply_result(Z3_apply_result g) { return reinterpret_cast<Z3_apply_result_ref *>(g); }
|
||||
inline Z3_apply_result of_apply_result(Z3_apply_result_ref * g) { return reinterpret_cast<Z3_apply_result>(g); }
|
||||
|
||||
#endif
|
333
src/api/api_user_theory.cpp
Normal file
333
src/api/api_user_theory.cpp
Normal file
|
@ -0,0 +1,333 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
api_user_theory.cpp
|
||||
|
||||
Abstract:
|
||||
API for external theories
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2012-02-29.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include<iostream>
|
||||
#include"z3.h"
|
||||
#include"api_log_macros.h"
|
||||
#include"api_context.h"
|
||||
#include"api_util.h"
|
||||
#include"user_smt_theory.h"
|
||||
|
||||
smt::user_theory * mk_t(Z3_theory t) {
|
||||
return reinterpret_cast<smt::user_theory*>(t);
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
///////////////////////////////
|
||||
// Theory plugin
|
||||
// No support for logging
|
||||
|
||||
Z3_theory Z3_mk_theory(Z3_context c, Z3_string th_name, void * ext_data) {
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
if (mk_c(c)->get_solver().get_scope_level() > 0) {
|
||||
SET_ERROR_CODE(Z3_INVALID_USAGE);
|
||||
return 0;
|
||||
}
|
||||
return reinterpret_cast<Z3_theory>(mk_user_theory(mk_c(c)->get_solver(), c, ext_data, th_name));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
void * Z3_theory_get_ext_data(Z3_theory t) {
|
||||
Z3_context c = Z3_theory_get_context(t);
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
void * r = mk_t(t)->get_ext_data();
|
||||
return r;
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_sort Z3_theory_mk_sort(Z3_context c, Z3_theory t, Z3_symbol s) {
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
sort * r = mk_t(t)->mk_sort(to_symbol(s));
|
||||
mk_c(c)->save_ast_trail(r);
|
||||
return of_sort(r);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_theory_mk_value(Z3_context c, Z3_theory t, Z3_symbol n, Z3_sort s) {
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
func_decl * d = mk_t(t)->mk_value_decl(to_symbol(n), to_sort(s));
|
||||
app * r = mk_c(c)->m().mk_const(d);
|
||||
mk_c(c)->save_ast_trail(r);
|
||||
return of_ast(r);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_theory_mk_constant(Z3_context c, Z3_theory t, Z3_symbol n, Z3_sort s) {
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
Z3_func_decl d = Z3_theory_mk_func_decl(c, t, n, 0, 0, s);
|
||||
app * r = mk_c(c)->m().mk_const(to_func_decl(d));
|
||||
mk_c(c)->save_ast_trail(r);
|
||||
return of_ast(r);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_func_decl Z3_theory_mk_func_decl(Z3_context c, Z3_theory t, Z3_symbol n,
|
||||
unsigned domain_size, Z3_sort const domain[],
|
||||
Z3_sort range) {
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
func_decl * r = mk_t(t)->mk_func_decl(to_symbol(n), domain_size, to_sorts(domain), to_sort(range));
|
||||
mk_c(c)->save_ast_trail(r);
|
||||
return of_func_decl(r);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_context Z3_theory_get_context(Z3_theory t) {
|
||||
Z3_context c = reinterpret_cast<Z3_context>(mk_t(t)->get_ext_context());
|
||||
RESET_ERROR_CODE();
|
||||
return c;
|
||||
}
|
||||
|
||||
void Z3_set_delete_callback(Z3_theory t, Z3_theory_callback_fptr f) {
|
||||
Z3_context c = Z3_theory_get_context(t);
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
mk_t(t)->set_delete_fptr(reinterpret_cast<smt::theory_callback_fptr>(f));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_set_reduce_app_callback(Z3_theory t, Z3_reduce_app_callback_fptr f) {
|
||||
Z3_context c = Z3_theory_get_context(t);
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
mk_t(t)->set_reduce_app_fptr(reinterpret_cast<reduce_app_fptr>(f));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_set_reduce_eq_callback(Z3_theory t, Z3_reduce_eq_callback_fptr f) {
|
||||
Z3_context c = Z3_theory_get_context(t);
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
mk_t(t)->set_reduce_eq_fptr(reinterpret_cast<reduce_eq_fptr>(f));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_set_reduce_distinct_callback(Z3_theory t, Z3_reduce_distinct_callback_fptr f) {
|
||||
Z3_context c = Z3_theory_get_context(t);
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
mk_t(t)->set_reduce_distinct_fptr(reinterpret_cast<reduce_distinct_fptr>(f));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_set_new_app_callback(Z3_theory t, Z3_theory_ast_callback_fptr f) {
|
||||
Z3_context c = Z3_theory_get_context(t);
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
mk_t(t)->set_new_app_fptr(reinterpret_cast<smt::theory_app_callback_fptr>(f));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_set_new_elem_callback(Z3_theory t, Z3_theory_ast_callback_fptr f) {
|
||||
Z3_context c = Z3_theory_get_context(t);
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
mk_t(t)->set_new_elem_fptr(reinterpret_cast<smt::theory_app_callback_fptr>(f));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_set_init_search_callback(Z3_theory t, Z3_theory_callback_fptr f) {
|
||||
Z3_context c = Z3_theory_get_context(t);
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
mk_t(t)->set_init_search_fptr(reinterpret_cast<smt::theory_callback_fptr>(f));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_set_push_callback(Z3_theory t, Z3_theory_callback_fptr f) {
|
||||
Z3_context c = Z3_theory_get_context(t);
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
mk_t(t)->set_push_fptr(reinterpret_cast<smt::theory_callback_fptr>(f));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_set_pop_callback(Z3_theory t, Z3_theory_callback_fptr f) {
|
||||
Z3_context c = Z3_theory_get_context(t);
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
mk_t(t)->set_pop_fptr(reinterpret_cast<smt::theory_callback_fptr>(f));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_set_restart_callback(Z3_theory t, Z3_theory_callback_fptr f) {
|
||||
Z3_context c = Z3_theory_get_context(t);
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
mk_t(t)->set_restart_fptr(reinterpret_cast<smt::theory_callback_fptr>(f));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_set_reset_callback(Z3_theory t, Z3_theory_callback_fptr f) {
|
||||
Z3_context c = Z3_theory_get_context(t);
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
mk_t(t)->set_reset_fptr(reinterpret_cast<smt::theory_callback_fptr>(f));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_set_final_check_callback(Z3_theory t, Z3_theory_final_check_callback_fptr f) {
|
||||
Z3_context c = Z3_theory_get_context(t);
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
mk_t(t)->set_final_check_fptr(reinterpret_cast<smt::theory_final_check_callback_fptr>(f));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_set_new_eq_callback(Z3_theory t, Z3_theory_ast_ast_callback_fptr f) {
|
||||
Z3_context c = Z3_theory_get_context(t);
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
mk_t(t)->set_new_eq_fptr(reinterpret_cast<smt::theory_app_app_callback_fptr>(f));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_set_new_diseq_callback(Z3_theory t, Z3_theory_ast_ast_callback_fptr f) {
|
||||
Z3_context c = Z3_theory_get_context(t);
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
mk_t(t)->set_new_diseq_fptr(reinterpret_cast<smt::theory_app_app_callback_fptr>(f));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_set_new_assignment_callback(Z3_theory t, Z3_theory_ast_bool_callback_fptr f) {
|
||||
Z3_context c = Z3_theory_get_context(t);
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
mk_t(t)->set_new_assignment_fptr(reinterpret_cast<smt::theory_app_bool_callback_fptr>(f));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_set_new_relevant_callback(Z3_theory t, Z3_theory_ast_callback_fptr f) {
|
||||
Z3_context c = Z3_theory_get_context(t);
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
mk_t(t)->set_new_relevant_fptr(reinterpret_cast<smt::theory_app_callback_fptr>(f));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_theory_assert_axiom(Z3_theory t, Z3_ast ax) {
|
||||
Z3_context c = Z3_theory_get_context(t);
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
mk_t(t)->assert_axiom(to_ast(ax));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_theory_assume_eq(Z3_theory t, Z3_ast lhs, Z3_ast rhs) {
|
||||
Z3_context c = Z3_theory_get_context(t);
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
mk_t(t)->assume_eq(to_ast(lhs), to_ast(rhs));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_theory_enable_axiom_simplification(Z3_theory t, Z3_bool flag) {
|
||||
Z3_context c = Z3_theory_get_context(t);
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
mk_t(t)->enable_axiom_simplification(flag == Z3_TRUE);
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
Z3_ast Z3_theory_get_eqc_root(Z3_theory t, Z3_ast n) {
|
||||
Z3_context c = Z3_theory_get_context(t);
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
return of_ast(mk_t(t)->get_root(to_ast(n)));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_theory_get_eqc_next(Z3_theory t, Z3_ast n) {
|
||||
Z3_context c = Z3_theory_get_context(t);
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
return of_ast(mk_t(t)->get_next(to_ast(n)));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
unsigned Z3_theory_get_num_parents(Z3_theory t, Z3_ast n) {
|
||||
Z3_context c = Z3_theory_get_context(t);
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
return mk_t(t)->get_num_parents(to_ast(n));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_theory_get_parent(Z3_theory t, Z3_ast n, unsigned i) {
|
||||
Z3_context c = Z3_theory_get_context(t);
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
return of_ast(mk_t(t)->get_parent(to_ast(n), i));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
unsigned Z3_theory_get_num_elems(Z3_theory t) {
|
||||
Z3_context c = Z3_theory_get_context(t);
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
return mk_t(t)->get_num_asts();
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_theory_get_elem(Z3_theory t, unsigned i) {
|
||||
Z3_context c = Z3_theory_get_context(t);
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
return of_ast(mk_t(t)->get_ast(i));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
unsigned Z3_theory_get_num_apps(Z3_theory t) {
|
||||
Z3_context c = Z3_theory_get_context(t);
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
return mk_t(t)->get_num_parents();
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_theory_get_app(Z3_theory t, unsigned i) {
|
||||
Z3_context c = Z3_theory_get_context(t);
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
return of_ast(mk_t(t)->get_parent(i));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_bool Z3_theory_is_value(Z3_theory t, Z3_ast n) {
|
||||
Z3_context c = Z3_theory_get_context(t);
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
return is_app(to_ast(n)) && mk_t(t)->get_family_id() == to_app(to_ast(n))->get_family_id();
|
||||
Z3_CATCH_RETURN(Z3_FALSE);
|
||||
}
|
||||
|
||||
Z3_bool Z3_theory_is_decl(Z3_theory t, Z3_func_decl d) {
|
||||
Z3_context c = Z3_theory_get_context(t);
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
return mk_t(t)->get_family_id() == to_func_decl(d)->get_family_id();
|
||||
Z3_CATCH_RETURN(Z3_FALSE);
|
||||
}
|
||||
|
||||
};
|
150
src/api/api_util.h
Normal file
150
src/api/api_util.h
Normal 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
|
164
src/arith_tactics/add_bounds.cpp
Normal file
164
src/arith_tactics/add_bounds.cpp
Normal file
|
@ -0,0 +1,164 @@
|
|||
/*++
|
||||
Copyright (c) 2011 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
add_bounds.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Strategy for bounding unbounded variables.
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2011-06-30.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include"add_bounds.h"
|
||||
#include"arith_decl_plugin.h"
|
||||
#include"ast_smt2_pp.h"
|
||||
#include"bound_manager.h"
|
||||
#include"for_each_expr.h"
|
||||
#include"assertion_set_util.h"
|
||||
|
||||
struct is_unbounded_proc {
|
||||
struct found {};
|
||||
arith_util m_util;
|
||||
bound_manager & m_bm;
|
||||
|
||||
is_unbounded_proc(bound_manager & bm):m_util(bm.m()), m_bm(bm) {}
|
||||
|
||||
void operator()(app * t) {
|
||||
if (is_uninterp_const(t) && (m_util.is_int(t) || m_util.is_real(t)) && (!m_bm.has_lower(t) || !m_bm.has_upper(t)))
|
||||
throw found();
|
||||
}
|
||||
|
||||
void operator()(var *) {}
|
||||
|
||||
void operator()(quantifier*) {}
|
||||
};
|
||||
|
||||
bool is_unbounded(assertion_set const & s) {
|
||||
ast_manager & m = s.m();
|
||||
bound_manager bm(m);
|
||||
bm(s);
|
||||
is_unbounded_proc proc(bm);
|
||||
return test(s, proc);
|
||||
}
|
||||
|
||||
struct add_bounds::imp {
|
||||
ast_manager & m;
|
||||
rational m_lower;
|
||||
rational m_upper;
|
||||
volatile bool m_cancel;
|
||||
|
||||
imp(ast_manager & _m, params_ref const & p):
|
||||
m(_m) {
|
||||
updt_params(p);
|
||||
}
|
||||
|
||||
void updt_params(params_ref const & p) {
|
||||
m_lower = p.get_rat(":add-bound-lower", rational(-2));
|
||||
m_upper = p.get_rat(":add-bound-upper", rational(2));
|
||||
}
|
||||
|
||||
void set_cancel(bool f) {
|
||||
m_cancel = f;
|
||||
}
|
||||
|
||||
struct add_bound_proc {
|
||||
arith_util m_util;
|
||||
bound_manager & m_bm;
|
||||
assertion_set & m_set;
|
||||
rational const & m_lower;
|
||||
rational const & m_upper;
|
||||
unsigned m_num_bounds;
|
||||
|
||||
add_bound_proc(bound_manager & bm, assertion_set & s, rational const & l, rational const & u):
|
||||
m_util(bm.m()),
|
||||
m_bm(bm),
|
||||
m_set(s),
|
||||
m_lower(l),
|
||||
m_upper(u) {
|
||||
m_num_bounds = 0;
|
||||
}
|
||||
|
||||
void operator()(app * t) {
|
||||
if (is_uninterp_const(t) && (m_util.is_int(t) || m_util.is_real(t))) {
|
||||
if (!m_bm.has_lower(t)) {
|
||||
m_set.assert_expr(m_util.mk_le(t, m_util.mk_numeral(m_upper, m_util.is_int(t))));
|
||||
m_num_bounds++;
|
||||
}
|
||||
if (!m_bm.has_upper(t)) {
|
||||
m_set.assert_expr(m_util.mk_ge(t, m_util.mk_numeral(m_lower, m_util.is_int(t))));
|
||||
m_num_bounds++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void operator()(var *) {}
|
||||
|
||||
void operator()(quantifier*) {}
|
||||
};
|
||||
|
||||
void operator()(assertion_set & s, model_converter_ref & mc) {
|
||||
mc = 0;
|
||||
if (s.inconsistent())
|
||||
return;
|
||||
as_st_report report("add-bounds", s);
|
||||
bound_manager bm(m);
|
||||
expr_fast_mark1 visited;
|
||||
add_bound_proc proc(bm, s, m_lower, m_upper);
|
||||
unsigned sz = s.size();
|
||||
for (unsigned i = 0; i < sz; i++)
|
||||
quick_for_each_expr(proc, visited, s.form(i));
|
||||
visited.reset();
|
||||
report_st_progress(":added-bounds", proc.m_num_bounds);
|
||||
TRACE("add_bounds", s.display(tout););
|
||||
}
|
||||
};
|
||||
|
||||
add_bounds::add_bounds(ast_manager & m, params_ref const & p):
|
||||
m_params(p) {
|
||||
m_imp = alloc(imp, m, p);
|
||||
}
|
||||
|
||||
add_bounds::~add_bounds() {
|
||||
dealloc(m_imp);
|
||||
}
|
||||
|
||||
void add_bounds::updt_params(params_ref const & p) {
|
||||
m_params = p;
|
||||
m_imp->updt_params(p);
|
||||
}
|
||||
|
||||
void add_bounds::get_param_descrs(param_descrs & r) {
|
||||
r.insert(":add-bound-lower", CPK_NUMERAL, "(default: -2) lower bound to be added to unbounded variables.");
|
||||
r.insert(":add-bound-upper", CPK_NUMERAL, "(default: 2) upper bound to be added to unbounded variables.");
|
||||
}
|
||||
|
||||
void add_bounds::operator()(assertion_set & s, model_converter_ref & mc) {
|
||||
m_imp->operator()(s, mc);
|
||||
}
|
||||
|
||||
void add_bounds::set_cancel(bool f) {
|
||||
if (m_imp)
|
||||
m_imp->set_cancel(f);
|
||||
}
|
||||
|
||||
void add_bounds::cleanup() {
|
||||
ast_manager & m = m_imp->m;
|
||||
imp * d = m_imp;
|
||||
#pragma omp critical (as_st_cancel)
|
||||
{
|
||||
d = m_imp;
|
||||
}
|
||||
dealloc(d);
|
||||
d = alloc(imp, m, m_params);
|
||||
#pragma omp critical (as_st_cancel)
|
||||
{
|
||||
m_imp = d;
|
||||
}
|
||||
}
|
50
src/arith_tactics/add_bounds.h
Normal file
50
src/arith_tactics/add_bounds.h
Normal file
|
@ -0,0 +1,50 @@
|
|||
/*++
|
||||
Copyright (c) 2011 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
add_bounds.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Strategy for bounding unbounded variables.
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2011-06-30.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _ADD_BOUNDS_H_
|
||||
#define _ADD_BOUNDS_H_
|
||||
|
||||
#include"assertion_set_strategy.h"
|
||||
|
||||
bool is_unbounded(assertion_set const & s);
|
||||
|
||||
class add_bounds : public assertion_set_strategy {
|
||||
struct imp;
|
||||
imp * m_imp;
|
||||
params_ref m_params;
|
||||
public:
|
||||
add_bounds(ast_manager & m, params_ref const & p = params_ref());
|
||||
virtual ~add_bounds();
|
||||
|
||||
virtual void updt_params(params_ref const & p);
|
||||
static void get_param_descrs(param_descrs & r);
|
||||
virtual void collect_param_descrs(param_descrs & r) { get_param_descrs(r); }
|
||||
|
||||
virtual void operator()(assertion_set & s, model_converter_ref & mc);
|
||||
|
||||
virtual void cleanup();
|
||||
|
||||
protected:
|
||||
virtual void set_cancel(bool f);
|
||||
};
|
||||
|
||||
inline as_st * mk_add_bounds(ast_manager & m, params_ref const & p = params_ref()) {
|
||||
return clean(alloc(add_bounds, m, p));
|
||||
}
|
||||
|
||||
#endif
|
198
src/arith_tactics/add_bounds_tactic.cpp
Normal file
198
src/arith_tactics/add_bounds_tactic.cpp
Normal file
|
@ -0,0 +1,198 @@
|
|||
/*++
|
||||
Copyright (c) 2011 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
add_bounds_tactic.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Tactic for bounding unbounded variables.
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2011-10-22.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include"tactical.h"
|
||||
#include"arith_decl_plugin.h"
|
||||
#include"ast_smt2_pp.h"
|
||||
#include"bound_manager.h"
|
||||
|
||||
struct is_unbounded_proc {
|
||||
struct found {};
|
||||
arith_util m_util;
|
||||
bound_manager & m_bm;
|
||||
|
||||
is_unbounded_proc(bound_manager & bm):m_util(bm.m()), m_bm(bm) {}
|
||||
|
||||
void operator()(app * t) {
|
||||
if (is_uninterp_const(t) && (m_util.is_int(t) || m_util.is_real(t)) && (!m_bm.has_lower(t) || !m_bm.has_upper(t)))
|
||||
throw found();
|
||||
}
|
||||
|
||||
void operator()(var *) {}
|
||||
|
||||
void operator()(quantifier*) {}
|
||||
};
|
||||
|
||||
bool is_unbounded(goal const & g) {
|
||||
ast_manager & m = g.m();
|
||||
bound_manager bm(m);
|
||||
bm(g);
|
||||
is_unbounded_proc proc(bm);
|
||||
return test(g, proc);
|
||||
}
|
||||
|
||||
class is_unbounded_probe : public probe {
|
||||
public:
|
||||
virtual result operator()(goal const & g) {
|
||||
return is_unbounded(g);
|
||||
}
|
||||
};
|
||||
|
||||
probe * mk_is_unbounded_probe() {
|
||||
return alloc(is_unbounded_probe);
|
||||
}
|
||||
|
||||
class add_bounds_tactic : public tactic {
|
||||
struct imp {
|
||||
ast_manager & m;
|
||||
rational m_lower;
|
||||
rational m_upper;
|
||||
volatile bool m_cancel;
|
||||
|
||||
imp(ast_manager & _m, params_ref const & p):
|
||||
m(_m) {
|
||||
updt_params(p);
|
||||
}
|
||||
|
||||
void updt_params(params_ref const & p) {
|
||||
m_lower = p.get_rat(":add-bound-lower", rational(-2));
|
||||
m_upper = p.get_rat(":add-bound-upper", rational(2));
|
||||
}
|
||||
|
||||
void set_cancel(bool f) {
|
||||
m_cancel = f;
|
||||
}
|
||||
|
||||
struct add_bound_proc {
|
||||
arith_util m_util;
|
||||
bound_manager & m_bm;
|
||||
goal & m_goal;
|
||||
rational const & m_lower;
|
||||
rational const & m_upper;
|
||||
unsigned m_num_bounds;
|
||||
|
||||
add_bound_proc(bound_manager & bm, goal & g, rational const & l, rational const & u):
|
||||
m_util(bm.m()),
|
||||
m_bm(bm),
|
||||
m_goal(g),
|
||||
m_lower(l),
|
||||
m_upper(u) {
|
||||
m_num_bounds = 0;
|
||||
}
|
||||
|
||||
void operator()(app * t) {
|
||||
if (is_uninterp_const(t) && (m_util.is_int(t) || m_util.is_real(t))) {
|
||||
if (!m_bm.has_lower(t)) {
|
||||
m_goal.assert_expr(m_util.mk_le(t, m_util.mk_numeral(m_upper, m_util.is_int(t))));
|
||||
m_num_bounds++;
|
||||
}
|
||||
if (!m_bm.has_upper(t)) {
|
||||
m_goal.assert_expr(m_util.mk_ge(t, m_util.mk_numeral(m_lower, m_util.is_int(t))));
|
||||
m_num_bounds++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void operator()(var *) {}
|
||||
|
||||
void operator()(quantifier*) {}
|
||||
};
|
||||
|
||||
virtual void operator()(goal_ref const & g,
|
||||
goal_ref_buffer & result,
|
||||
model_converter_ref & mc,
|
||||
proof_converter_ref & pc,
|
||||
expr_dependency_ref & core) {
|
||||
mc = 0; pc = 0; core = 0;
|
||||
tactic_report report("add-bounds", *g);
|
||||
bound_manager bm(m);
|
||||
expr_fast_mark1 visited;
|
||||
add_bound_proc proc(bm, *(g.get()), m_lower, m_upper);
|
||||
unsigned sz = g->size();
|
||||
for (unsigned i = 0; i < sz; i++)
|
||||
quick_for_each_expr(proc, visited, g->form(i));
|
||||
visited.reset();
|
||||
g->inc_depth();
|
||||
result.push_back(g.get());
|
||||
if (proc.m_num_bounds > 0)
|
||||
g->updt_prec(goal::UNDER);
|
||||
report_tactic_progress(":added-bounds", proc.m_num_bounds);
|
||||
TRACE("add_bounds", g->display(tout););
|
||||
}
|
||||
};
|
||||
|
||||
imp * m_imp;
|
||||
params_ref m_params;
|
||||
|
||||
public:
|
||||
add_bounds_tactic(ast_manager & m, params_ref const & p):
|
||||
m_params(p) {
|
||||
m_imp = alloc(imp, m, p);
|
||||
}
|
||||
|
||||
virtual tactic * translate(ast_manager & m) {
|
||||
return alloc(add_bounds_tactic, m, m_params);
|
||||
}
|
||||
|
||||
virtual ~add_bounds_tactic() {
|
||||
dealloc(m_imp);
|
||||
}
|
||||
|
||||
virtual void updt_params(params_ref const & p) {
|
||||
m_params = p;
|
||||
m_imp->updt_params(p);
|
||||
}
|
||||
|
||||
virtual void collect_param_descrs(param_descrs & r) {
|
||||
r.insert(":add-bound-lower", CPK_NUMERAL, "(default: -2) lower bound to be added to unbounded variables.");
|
||||
r.insert(":add-bound-upper", CPK_NUMERAL, "(default: 2) upper bound to be added to unbounded variables.");
|
||||
}
|
||||
|
||||
virtual void operator()(goal_ref const & g,
|
||||
goal_ref_buffer & result,
|
||||
model_converter_ref & mc,
|
||||
proof_converter_ref & pc,
|
||||
expr_dependency_ref & core) {
|
||||
(*m_imp)(g, result, mc, pc, core);
|
||||
}
|
||||
|
||||
virtual void cleanup() {
|
||||
ast_manager & m = m_imp->m;
|
||||
imp * d = m_imp;
|
||||
#pragma omp critical (tactic_cancel)
|
||||
{
|
||||
d = m_imp;
|
||||
}
|
||||
dealloc(d);
|
||||
d = alloc(imp, m, m_params);
|
||||
#pragma omp critical (tactic_cancel)
|
||||
{
|
||||
m_imp = d;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void set_cancel(bool f) {
|
||||
if (m_imp)
|
||||
m_imp->set_cancel(f);
|
||||
}
|
||||
};
|
||||
|
||||
tactic * mk_add_bounds_tactic(ast_manager & m, params_ref const & p) {
|
||||
return clean(alloc(add_bounds_tactic, m, p));
|
||||
}
|
34
src/arith_tactics/add_bounds_tactic.h
Normal file
34
src/arith_tactics/add_bounds_tactic.h
Normal file
|
@ -0,0 +1,34 @@
|
|||
/*++
|
||||
Copyright (c) 2011 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
add_bounds.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Tactic for bounding unbounded variables.
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2011-06-30.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _ADD_BOUNDS_H_
|
||||
#define _ADD_BOUNDS_H_
|
||||
|
||||
#include"params.h"
|
||||
|
||||
class ast_manager;
|
||||
class goal;
|
||||
class tactic;
|
||||
class probe;
|
||||
|
||||
bool is_unbounded(goal const & g);
|
||||
probe * mk_is_unbounded_probe();
|
||||
|
||||
tactic * mk_add_bounds_tactic(ast_manager & m, params_ref const & p = params_ref());
|
||||
|
||||
#endif
|
240
src/arith_tactics/bound_manager.cpp
Normal file
240
src/arith_tactics/bound_manager.cpp
Normal 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";
|
||||
}
|
||||
}
|
111
src/arith_tactics/bound_manager.h
Normal file
111
src/arith_tactics/bound_manager.h
Normal 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
|
956
src/arith_tactics/bound_propagator.cpp
Normal file
956
src/arith_tactics/bound_propagator.cpp
Normal 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);
|
||||
}
|
||||
|
||||
|
||||
|
265
src/arith_tactics/bound_propagator.h
Normal file
265
src/arith_tactics/bound_propagator.h
Normal 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
|
349
src/arith_tactics/degree_shift_tactic.cpp
Normal file
349
src/arith_tactics/degree_shift_tactic.cpp
Normal 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)));
|
||||
}
|
||||
|
31
src/arith_tactics/degree_shift_tactic.h
Normal file
31
src/arith_tactics/degree_shift_tactic.h
Normal 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
|
429
src/arith_tactics/diff_neq_tactic.cpp
Normal file
429
src/arith_tactics/diff_neq_tactic.cpp
Normal 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));
|
||||
}
|
||||
|
||||
|
||||
|
32
src/arith_tactics/diff_neq_tactic.h
Normal file
32
src/arith_tactics/diff_neq_tactic.h
Normal 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
|
358
src/arith_tactics/fix_dl_var_tactic.cpp
Normal file
358
src/arith_tactics/fix_dl_var_tactic.cpp
Normal 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));
|
||||
}
|
33
src/arith_tactics/fix_dl_var_tactic.h
Normal file
33
src/arith_tactics/fix_dl_var_tactic.h
Normal 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
|
1715
src/arith_tactics/fm_tactic.cpp
Normal file
1715
src/arith_tactics/fm_tactic.cpp
Normal file
File diff suppressed because it is too large
Load diff
33
src/arith_tactics/fm_tactic.h
Normal file
33
src/arith_tactics/fm_tactic.h
Normal 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
|
366
src/arith_tactics/lia2pb_tactic.cpp
Normal file
366
src/arith_tactics/lia2pb_tactic.cpp
Normal 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));
|
||||
}
|
||||
|
28
src/arith_tactics/lia2pb_tactic.h
Normal file
28
src/arith_tactics/lia2pb_tactic.h
Normal 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
|
279
src/arith_tactics/linear_equation.cpp
Normal file
279
src/arith_tactics/linear_equation.cpp
Normal 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);
|
||||
}
|
||||
|
85
src/arith_tactics/linear_equation.h
Normal file
85
src/arith_tactics/linear_equation.h
Normal 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
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
404
src/arith_tactics/lu.h
Normal 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
|
135
src/arith_tactics/mip_tactic.cpp
Normal file
135
src/arith_tactics/mip_tactic.cpp
Normal 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));
|
||||
}
|
30
src/arith_tactics/mip_tactic.h
Normal file
30
src/arith_tactics/mip_tactic.h
Normal 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
|
480
src/arith_tactics/nla2bv_tactic.cpp
Normal file
480
src/arith_tactics/nla2bv_tactic.cpp
Normal 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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
30
src/arith_tactics/nla2bv_tactic.h
Normal file
30
src/arith_tactics/nla2bv_tactic.h
Normal 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
|
||||
|
211
src/arith_tactics/normalize_bounds_tactic.cpp
Normal file
211
src/arith_tactics/normalize_bounds_tactic.cpp
Normal 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));
|
||||
}
|
30
src/arith_tactics/normalize_bounds_tactic.h
Normal file
30
src/arith_tactics/normalize_bounds_tactic.h
Normal 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
|
102
src/arith_tactics/pb2bv_model_converter.cpp
Normal file
102
src/arith_tactics/pb2bv_model_converter.cpp
Normal 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();
|
||||
}
|
39
src/arith_tactics/pb2bv_model_converter.h
Normal file
39
src/arith_tactics/pb2bv_model_converter.h
Normal 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
|
1051
src/arith_tactics/pb2bv_tactic.cpp
Normal file
1051
src/arith_tactics/pb2bv_tactic.cpp
Normal file
File diff suppressed because it is too large
Load diff
30
src/arith_tactics/pb2bv_tactic.h
Normal file
30
src/arith_tactics/pb2bv_tactic.h
Normal 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
|
421
src/arith_tactics/probe_arith.cpp
Normal file
421
src/arith_tactics/probe_arith.cpp
Normal 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);
|
||||
}
|
39
src/arith_tactics/probe_arith.h
Normal file
39
src/arith_tactics/probe_arith.h
Normal 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
|
563
src/arith_tactics/propagate_ineqs_tactic.cpp
Normal file
563
src/arith_tactics/propagate_ineqs_tactic.cpp
Normal 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;
|
||||
}
|
||||
}
|
42
src/arith_tactics/propagate_ineqs_tactic.h
Normal file
42
src/arith_tactics/propagate_ineqs_tactic.h
Normal 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
|
909
src/arith_tactics/purify_arith_tactic.cpp
Normal file
909
src/arith_tactics/purify_arith_tactic.cpp
Normal 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));
|
||||
}
|
58
src/arith_tactics/purify_arith_tactic.h
Normal file
58
src/arith_tactics/purify_arith_tactic.h
Normal 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
|
||||
|
446
src/arith_tactics/recover_01_tactic.cpp
Normal file
446
src/arith_tactics/recover_01_tactic.cpp
Normal 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));
|
||||
}
|
42
src/arith_tactics/recover_01_tactic.h
Normal file
42
src/arith_tactics/recover_01_tactic.h
Normal 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
|
170
src/arith_tactics/vsubst_tactic.cpp
Normal file
170
src/arith_tactics/vsubst_tactic.cpp
Normal 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);
|
||||
}
|
30
src/arith_tactics/vsubst_tactic.h
Normal file
30
src/arith_tactics/vsubst_tactic.h
Normal 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
|
||||
|
555
src/core_tactics/ctx_simplify_tactic.cpp
Normal file
555
src/core_tactics/ctx_simplify_tactic.cpp
Normal 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;
|
||||
}
|
||||
}
|
||||
|
56
src/core_tactics/ctx_simplify_tactic.h
Normal file
56
src/core_tactics/ctx_simplify_tactic.h
Normal 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
|
149
src/core_tactics/distribute_forall_tactic.cpp
Normal file
149
src/core_tactics/distribute_forall_tactic.cpp
Normal 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);
|
||||
}
|
26
src/core_tactics/distribute_forall_tactic.h
Normal file
26
src/core_tactics/distribute_forall_tactic.h
Normal 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
|
1076
src/core_tactics/elim_uncnstr_tactic.cpp
Normal file
1076
src/core_tactics/elim_uncnstr_tactic.cpp
Normal file
File diff suppressed because it is too large
Load diff
30
src/core_tactics/elim_uncnstr_tactic.h
Normal file
30
src/core_tactics/elim_uncnstr_tactic.h
Normal 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
|
||||
|
126
src/core_tactics/nnf_tactic.cpp
Normal file
126
src/core_tactics/nnf_tactic.cpp
Normal 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);
|
||||
}
|
30
src/core_tactics/nnf_tactic.h
Normal file
30
src/core_tactics/nnf_tactic.h
Normal 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
|
||||
|
252
src/core_tactics/occf_tactic.cpp
Normal file
252
src/core_tactics/occf_tactic.cpp
Normal 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));
|
||||
}
|
||||
|
34
src/core_tactics/occf_tactic.h
Normal file
34
src/core_tactics/occf_tactic.h
Normal 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
|
||||
|
275
src/core_tactics/propagate_values_tactic.cpp
Normal file
275
src/core_tactics/propagate_values_tactic.cpp
Normal 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));
|
||||
}
|
||||
|
29
src/core_tactics/propagate_values_tactic.h
Normal file
29
src/core_tactics/propagate_values_tactic.h
Normal 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
|
139
src/core_tactics/simplify_tactic.cpp
Normal file
139
src/core_tactics/simplify_tactic.cpp
Normal 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);
|
||||
}
|
||||
|
54
src/core_tactics/simplify_tactic.h
Normal file
54
src/core_tactics/simplify_tactic.h
Normal 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
|
791
src/core_tactics/solve_eqs_tactic.cpp
Normal file
791
src/core_tactics/solve_eqs_tactic.cpp
Normal 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));
|
||||
}
|
||||
|
30
src/core_tactics/solve_eqs_tactic.h
Normal file
30
src/core_tactics/solve_eqs_tactic.h
Normal 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
Loading…
Add table
Add a link
Reference in a new issue